• OS第4次实验报告:文件系统


    • 姓名:巫艳珍
    • 学号:201821121034
    • 班级:计算1812

    1. 编写程序

    在服务器上用Vim编写一个程序:实现Linux系统命令ls -lai的功能,给出源代码。

    源代码:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<unistd.h>
    #include<dirent.h>
    #include<sys/stat.h>
    #include<sys/types.h>
    #include<fcntl.h>
    #include<pwd.h>
    #include<grp.h>
    #include<time.h>
    
    
    void filedir(const char* );//打开目录
    
    void file_type(const struct stat* );//文件类型
    void file_power(const struct stat* );//文件权限
    void file_id(const struct stat* );//文件用户id与组id
    void print_fileinfo(const char* , const struct stat*);//打印文件信息
    void linkprint(const char* );
    
    
    //打开文件目录
    void filedir(const char* dir)
    {
        DIR* pdir = opendir(dir); 
        struct dirent* pd = NULL;
        int ret_chdir = chdir(dir);
        if(pdir == NULL){
            printf("open dir error!
    ");
            exit(1);
        } 
        while(pd = readdir(pdir)) // 判断是否读取到目录尾
        {
            char* name = pd->d_name; // 获取文件名
            struct stat file = {}; // 定义结构体变量
            int buf = lstat(name, &file); // 获取文件信息
            if(buf == -1) // 读取文件错误
                printf("%s error!", name);
            else if(strcmp(name,".") && strcmp(name,"..")) // 不输出当前目录与上一级目录
                print_fileinfo(name, &file);
        }
    }
    //判断并打印文件类型
    void file_type(const struct stat* file) 
    {
        mode_t mode = file->st_mode;
    
        if     (S_ISREG(mode))  printf("-"); // 普通文件
        else if(S_ISDIR(mode))  printf("d"); // 目录文件
        else if(S_ISCHR(mode))  printf("c"); // 字符设备文件
        else if(S_ISBLK(mode))  printf("b"); // 块设备文件
        else if(S_ISFIFO(mode)) printf("p"); // 管道文件
        else if(S_ISLNK(mode))  printf("l"); // 链接文件
        else                    printf("s"); // socket文件
    }
    //文件权限
    void file_power(const struct stat* file)
    {
        mode_t mode = file->st_mode;
    
    
        printf("%c", mode&S_IRUSR?'r':'-');
        printf("%c", mode&S_IWUSR?'w':'-');
        printf("%c", mode&S_IXUSR?'x':'-');
    
    
        printf("%c", mode&S_IRGRP?'r':'-');
        printf("%c", mode&S_IWGRP?'w':'-');
        printf("%c", mode&S_IXGRP?'x':'-');
    
        printf("%c", mode&S_IROTH?'r':'-');
        printf("%c", mode&S_IWOTH?'w':'-');
        printf("%c ", mode&S_IXOTH?'x':'-');
    } 
    //文件用户id与组id
    void file_id(const struct stat* file)
    {
    
        struct passwd* pwd;
        pwd = getpwuid(file->st_uid);
        printf("%s ",pwd->pw_name);
    
        struct group* grp;
        grp = getgrgid(file->st_gid);
        printf("%s ",grp->gr_name);
    
       
    }
    
    void print_fileinfo(const char* name, const struct stat* file)
    {   
    
        file_type(file); // 文件类型
    
         printf("%ld ",(int)file->st_ino);//添加索引号
        file_power(file); // 打印文件权限
        printf("%d ", file->st_nlink); // 硬链接数
        file_id(file); //用户id与组id
        printf("%5ld ", file->st_size); // 打印文件大小
        ctime_r(&file.st_mtime,buf);        //上一次被修改的时间
        buf[16] ='';
        printf("%s ", buf);
        printf("%s ", name); // 打印文件名
        if(S_ISLNK(file->st_mode)) 
            linkprint(name);
        puts("");
    }
    
    void linkprint(const char* name)
    {
        char buf[512] = "123";
        if(0 == readlink(name, buf, sizeof(buf)))
            perror("readlink");
        printf("-> %s ",buf);
    }
    
     int main()
     {     char dir[512] = {};
        strcpy(dir,"./");
         struct stat file = {};
        if(lstat(dir, &file) == -1)//文件属性 
            perror("stat");
            exit(EXIT_FAILURE);
    
        if(S_ISDIR(file.st_mode)) 
            filedir(dir);
        else
            print_fileinfo(dir, &file);
         return 0;
    
     }

    2. 分析运行结果

    给出运行结果截图,对于每一列是如何获取的,结合源代码做解释

     对比命令ls -lai:

    •  索引号:
    printf("%ld ",(int)file->st_ino);//添加索引号
    • 文件权限:在打印文件信息时调用file_power函数来打印文件权限:
    void file_power(const struct stat* file)
    {
        mode_t mode = file->st_mode;
    
    
        printf("%c", mode&S_IRUSR?'r':'-');
        printf("%c", mode&S_IWUSR?'w':'-');
        printf("%c", mode&S_IXUSR?'x':'-');
    
    
        printf("%c", mode&S_IRGRP?'r':'-');
        printf("%c", mode&S_IWGRP?'w':'-');
        printf("%c", mode&S_IXGRP?'x':'-');
    
        printf("%c", mode&S_IROTH?'r':'-');
        printf("%c", mode&S_IWOTH?'w':'-');
        printf("%c ", mode&S_IXOTH?'x':'-');
    } 
    • 硬链接数

     若一个 inode 号对应多个文件名,则称这些文件为硬链接,硬链接就是同一个文件使用了多个别名。

    实现代码:

    printf("%d ", file->st_nlink); // 硬链接数
    • 用户id与组id:调用函数
      file_id(file); 
    struct passwd* pwd;
    pwd = getpwuid(file->st_uid);
    printf("%s ",pwd->pw_name);
    
    struct group* grp;
    grp = getgrgid(file->st_gid);
    printf("%s ",grp->gr_name);

    这里用到两个结构体,分别如下:

    (1)struct passwd:

    #include <sys/types.h>
    #include <pwd.h>
    struct passwd
    {
      char *pw_name;                /* 用户登录名 */
      char *pw_passwd;              /* 密码(加密后) */
      __uid_t pw_uid;               /* 用户ID */
      __gid_t pw_gid;               /* 组ID */
      char *pw_gecos;               /* 详细用户名 */
      char *pw_dir;                 /* 用户目录 */
      char *pw_shell;               /* Shell程序名 */
    };

    (2)struct group:

    #include <sys/types.h>
    #include <grp.h>
    struct group
    {
      char *gr_name;                  /* 组名 */
      char *gr_passwd;              /* 密码 */
      __gid_t gr_gid;                  /* 组ID */
      char **gr_mem;                  /* 组成员名单 */
    }
    • 打印文件大小(即文件占用的空间):
    printf("%5ld ", file->st_size); // 打印文件大小
    • 上一次被修改的时间:
    ctime_r(&file.st_mtime,buf);        //上一次被修改的时间
    buf[16] ='';
    printf("%s ", buf);

    与文件时间有关的三个方面的管理属性:

    stat.st_atime(数据的最后访问时间)、stat.st_mtime(数据的最后修改时间)、stat.st_ctime(i节点最后更改时间)

    • 文件名:
    printf("%s ", name); // 打印文件名

    3. 通过该实验产生新的疑问及解答

    疑问1:索引号的打印与ls -lai的命令不同,但total的算法还未找到解决方法

    疑问2:获得文件上一次修改的时间有没有其他的写法

    解答:可以定义一个结构体,struct time* T = localtime(&file->st_mtime);再利用链表形式打印出来。

  • 相关阅读:
    按钮常用
    MySQL常用Json函数
    MySQL所有函数及操作符
    MySQL常用时间函数
    MySQL常用聚合函数
    Shiro整合Spring
    Shiro集成Web
    Shrio授权验证详解
    Shrio认证详解+自定义Realm
    Shiro入门
  • 原文地址:https://www.cnblogs.com/will-h/p/12810863.html
Copyright © 2020-2023  润新知