文件系统1

文件系统

  1. 目录和文件(比如类似于ls的实现)
  • 获取文件属性
    • int stat(const char * path, struct stat *buf);// 获取文件信息,存储到buf中,返回成功失败,,面对符号链接文件时获取的是所指向的目标文件的属性
    • lstat:面对符号链接文件时获取的是符号链接文件的属性,不对符号链接文件进行展开
    • stat 命令同样可以查看文件的属性,通过文件路径
    • fstat:通过文件描述符获取属性
    • st_mode 文件类型,mode_t 16位整型数,9bits基本位,u+s g+s t+s 3位,七种文件类型, (& 0 被抹除 1 保留)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>

static off_t flen(const char* fname)
{
    struct stat res;
    if (stat(fname, &res) < 0)
    {
        perror("stat");
        exit(1);
    }
    return res.st_size; // off_t类型返回值
}
int main(int argc, char ** argv)
{
    if (argc < 2)
    {
        fprintf(stderr, "usage\n");
        exit(1);
    }

    printf("%lld\n", (long long)flen(argv[1]));
    return  0;
}
// 查看文件类型
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>


static int ftype(const char* fname)
{
    struct stat res;
    if (stat(fname, &res) < 0)
    {
        perror("stat");
        exit(1);
    }

    if (S_ISREG(res.st_mode))
    {
        return '-'; // 常规文件
    }
    else if (S_ISDIR(res.st_mode))
    {
        return 'd'; // 目录文件
    }
        // 。。。
    else
    {
    }

    return '?';
}


int main(int argc, char ** argv)
{
    if (argc < 2)
    {
        fprintf(stderr, "usage\n");
        exit(1);
    }

    char c = ftype(argv[1]);
    printf("%c\n", c);

    return 0;
}
  • 文件的访问权限问题: st_mode 是一个16位的位图,用于表示文件类型,文件访问权限,及特殊位
  • umask:权限0666 & ~umask 目的是防止权限过松的文件
  • chmod(const char * file, mode_t );
  • fchmod
  • 粘住位t位 把某一个命令使用痕迹保留 tmp目录就是t位
  • 文件系统:fat ufs…
    fat:静态单链表,分区,承载能力有限。缺点:单向
    ufs:同一时代的产物
    文件或数据的存储、管理
  • 硬链接;同义词–特点:与目录项是的同义词,并建立硬链接有限制,不能给分区和目录建立
  • 符号链接 ls -s (symble) inode与原来文件不相同 link(const char* old, const char * new path); 符号链接的优点是可以夸分区,可以给目录建立
  • remove(const char * path); 删除一个文件
  • rename(const char * oldchar, const char * new_path); 改变名字或改变位置
  • utime:可以更改文件的最后读的时间和最后修改的时间
  • 目录的创建和销毁:int mkdir(const char* pathname); int rmdir(const char * pathname);
  • 更改当前工作路径 int chdir(const char * pathname); 修改进程的工作路径
  • 分析目录、读取目录内容
    glob(): 分析模式 解析模式/通配符 find pathnames matching a pattern
    int glob(const char *pattern, int flags,
    int (*errfunc) (const char *epath, int eerrno), // 保存出错路径出错 原因
    glob_t *pglob); // 解析的结果存放 eg append 追加到pglob中
    void globfree(glob_t *pglob); // 释放glob申请的空间
typedef struct {
               size_t   gl_pathc;    /* Count of paths matched so far
  */
               char   **gl_pathv;    /* List of matched pathnames.  *
/
               size_t   gl_offs;     /* Slots to reserve in gl_pathv.
  */
           } glob_t;
#include <stdio.h>
#include <stdlib.h>
#include <glob.h>

#define PAT "/etc/a*.conf"
// .* 是查找所有文件,   /* 是查找文件, 不包括隐藏的
// glob 解析模式或者通配符

// int errfunc_(const char * errpath, int errno)
// {
//     puts(errpath);
//     fprintf(stderr, "error msg:%s\n", strerror(error));
//     return 0;
// }

int main(int argc, char ** argv)
{
    glob_t  globalres;
    // 解析etc下面的所有a开头的conf文件
    int err = glob(PAT,0, NULL, &globalres);
    
    if (err)
    {
        printf("error code = %d\n", err);
        exit(1);
    }

    int i = 0;
    for (i = 0; i < globalres.gl_pathc;i++)
    {
        puts(globalres.gl_pathv[i]);
    }
    globfree(&globalres)

    return 0;
}

DIR* opendir(const char* name); 一对,打开的肯定在堆空间,后面会进行释放
closedir

#include <stdio.h>
#include <stdlib.h>
#include <glob.h>
#include <dirent.h>

#define PAT "/etc"   // etc下面所有的文件  *代表pattern 

int main()
{
    DIR * dp = opendir(PAT);
    struct dirent * cur;

    if (dp == NULL)
    {

        perror("opendir");
        exit(1);
    }

    while ((cur = readdir(dp)) != NULL)
    {
        puts(cur->d_name);
    }

    closedir();
    return 0;
}

seekdir()
rewinddir
telldir()
du命令 当前路径所占的大小
du filename 文件的大小
du filename1 filename2 filename3 分析多个文件或路径所占的大小
// 实现一个du的命令

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <glob.h>
#include <string.h>

#define PATHSIZE 1024

static int path_noloop(const char* path)
{
    char * pos = strrchr(path,'/'); // 右侧第一个/的位置
    if (pos == NULL)
    {
        exit(1);
    }
    if (strcmp(pos + 1, ".") == 0 || strcmp(pos + 1, "..") == 0)
        return 0;
    return 1;
}

static int64_t mydu(const char* path)
{
    // #if 0
    // // path 为非目录
    // st_blocks / 2
    // return;
    // // path 为目录文件
    // path/*
    // glob()
    // stat()

    // path/.*
    // glob()
    // #endif

    // 如果一个变量完全出现在递归点之前或者递归点之后,可以将变量放在静态区,节省栈空间
    static struct stat statres;
    static char nextpath[PATHSIZE];

    // 存在递归点中,使用auto存储
    glob_t globres;
    int64_t sum = 0;
    int i;

    if (lstat(path, &statres) < 0)  // 获取文件属性,存放到statres中
    {
        perror("lstat");
        exit(1);
    }
    if (!S_ISDIR(statres.st_mode)) // 文件是个dir
    {
        return statres.st_blocks;
    }
    // dir
    strncpy(nextpath, path,PATHSIZE);
    strncat(nextpath, "/*", PATHSIZE);  // 拼接  路径/* 的所有文件
    if (glob(nextpath, 0, NULL, &globres) < 0)
    {
        // 此时已经将所有非隐藏文件解析到res中
        fprintf(stderr, "glob");
        exit(1);
    }
    strncpy(nextpath, path, PATHSIZE);
    strncat(nextpath, "/.*", PATHSIZE);
    if (glob(nextpath , GLOB_APPEND , NULL, &globres) < 0)
    {
        // 解析隐藏文件,追加到res中
        fprintf(stderr, "glob()");
        exit(1);
    }

    
    sum = statres.st_blocks;
    for (i = 0; i < globres.gl_pathc;i++)
        // 没有. ..这种导致循环递归的情况需要进行递归,否则直接退
        if(path_noloop(globres.gl_pathv[i]))
            sum += mydu(globres.gl_pathv[i]);
    // sum += statres.st_blocks;
    globfree(&globres);
    return sum;
}

int main(int argc, char** argv)
{
    if (argc < 2)
    {
        fprintf(stderr, "usage");
        exit(1);
    }

    printf("%lld\n", mydu(argv[1])/ 2);
    return 0;
}

测试

du /etc/
mydu /etc
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值