zoukankan      html  css  js  c++  java
  • 操作系统第4次实验报告:文件系统

    • 林伟强
    • 201821121010
    • 计算1811

    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<time.h>
    #include<pwd.h>
    #include<grp.h>
    
    void error_printf(const char* );
    
    void list_dir(const char* );
    void list_message(const char* , const struct stat*);
    
    
    void file_type(const struct stat* );
    void file_power(const struct stat* );
    void file_id(const struct stat* );
    
    void file_mtime(const struct stat* );
    
    void link_printf(const char* );
    void error_printf(const char* funname)
    {
        perror(funname);
        exit(EXIT_FAILURE);
        /* 
        * EXIT_SUCCESS和EXIT_FAILURE是两个常量。
        * EXIT_SUCCESS=0,EXIT_FAILURE=1。
        * 0表示程序寿终正寝,1表示死于非命。
        */
    }
    
    
    void list_dir(const char* pathname)
    {
        DIR* ret_opendir = opendir(pathname); // 打开目录"pathname"
        if(ret_opendir == NULL)
            error_printf("opendir");
    
        int ret_chdir = chdir(pathname); // 改变工作目录至"pathname",便于stat函数的使用
        if(ret_chdir == -1)
            error_printf("chdir");
    
        struct dirent* ret_readdir = NULL; // 定义readdir函数返回的结构体变量
        while(ret_readdir = readdir(ret_opendir)) // 判断是否读取到目录尾
        {
            char* filename = ret_readdir->d_name; // 获取文件名
            struct stat file_message = {}; // 定义stat函数返回的结构体变量
            int ret_stat = lstat(filename, &file_message); // 获取文件信息
            if(ret_stat == -1) // stat读取文件错误则输出提示信息
                printf("%s error!", filename);
            else if(strcmp(filename,".") && strcmp(filename,"..")) // 不输出当前目录与上一级目录
                list_message(filename, &file_message);
        }
    }
    
    void list_message(const char* filename, const struct stat* file_message)
    {   
    
        file_type(file_message); // 判断打印文件类型
    
     printf("%d ",(int)file_message->st_ino);//添加索引号
        file_power(file_message); // 判断并打印文件权限
        printf("%d ", file_message->st_nlink); // 打印硬链接数
        file_id(file_message); // 转换并打印用户id与组id
        printf("%5ld ", file_message->st_size); // 打印文件大小
        file_mtime(file_message); // 打印文件最后修改时间
        printf("%s ", filename); // 打印文件名
        if(S_ISLNK(file_message->st_mode)) // 如果是软链接文件,打印其指向的位置
            link_printf(filename);
        puts("");
    }
    void file_type(const struct stat* file_message) 
    {
        mode_t mode = file_message->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_message)
    {
        mode_t mode = file_message->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':'-');
    }
    
    void file_id(const struct stat* file_message)
    {
    
        struct passwd* pwd;
        pwd = getpwuid(file_message->st_uid);
        printf("%s ",pwd->pw_name);
    
        struct group* grp;
        grp = getgrgid(file_message->st_gid);
        printf("%s ",grp->gr_name);
    
       
    }
    
    void file_mtime(const struct stat* file_message)
    {
        struct tm* t = localtime(&file_message->st_mtime);
        printf("%2d月 %2d %02d:%02d ", t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min);
    }
    
    void link_printf(const char* filename)
    {
        char buf[1024] = "123";
        if(0 == readlink(filename, buf, sizeof(buf)))
            error_printf("readlink");
        printf("-> %s ",buf);
    }

     int main()
     { char path[1024] = {};
    strcpy(path,"./");
     struct stat file_message = {};

    int ret_stat = lstat(path, &file_message);
    if(ret_stat == -1)
    error_printf("stat");

    if(S_ISDIR(file_message.st_mode)) // 判断是否为目录
     list_dir(path);
    else
    list_message(path, &file_message);
     return 0;

     }

     

    2. 分析运行结果

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

    suqiankun@jmu-cs-ubuntu:~$ ls -lai
    total 160
    920635 drwx------   6 suqiankun ubuntu  4096 Apr 27 09:52 .
    131195 drwxr-xr-x 129 root      root    4096 Apr 25 21:52 ..
    920658 -rw-------   1 suqiankun ubuntu 10359 Apr 27 10:38 .bash_history
    920636 -rw-r--r--   1 suqiankun ubuntu   220 Apr  5  2018 .bash_logout
    920638 -rw-r--r--   1 suqiankun ubuntu  3771 Apr  5  2018 .bashrc
    920656 drwx------   2 suqiankun ubuntu  4096 Mar 11 16:01 .cache

    第一列为索引号

    第二列

    drwxr-xr-x代表文件的类型及权限

    以d开头的为文件夹,以-开头的为文件,

    以l开头的为连接文件

    第三列:文件的链接数.

    第四列:拥有文件的用户

    第五列:拥有文件的组

    第六列:文件的大小。

    第七列:文件最后的修改时间。

    第八列:文件名

     

    以上图一为实验代码所得 图二为ls -lai

    添加索引号

     printf("%d ",(int)file_message->st_ino);//添加索引号

    第二列

    drwxr-xr-x代表文件的类型及权限

    以d开头的为文件夹,以-开头的为文件,

    以l开头的为连接文件


     void file_type(const struct stat* file_message)
     {
     mode_t mode = file_message->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_message)
     {
     mode_t mode = file_message->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':'-');
    }

    第三列:文件的链接数.

      printf("%d ", file_message->st_nlink); // 打印硬链接数

    第四列:拥有文件的用户

     struct passwd* pwd;
    pwd = getpwuid(file_message->st_uid);
     printf("%s ",pwd->pw_name);

    第五列:拥有文件的组

    struct group* grp;
     grp = getgrgid(file_message->st_gid);
     printf("%s ",grp->gr_name);

    第六列:文件的大小。

    printf("%5ld ", file_message->st_size); // 打印文件大小

    第七列:文件最后的修改时间。

    void file_mtime(const struct stat* file_message)
     {
     struct tm* t = localtime(&file_message->st_mtime);
     printf("%2d月 %2d %02d:%02d ", t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm_min);
    }

    第八列:文件名

      printf("%s ", filename); // 打印文件名   

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

    实验中文件最后修改时间和文件类型和权限是实验中最困难的地方

  • 相关阅读:
    视频智能分析系统EasyCVR视频流媒体安防监控云服务实现城市视频智能化应用
    Windows/Android/iOS平台H265编码视频播放器EasyPlayerRTSP中socket选项之keepalive设置介绍
    【解决方案】人脸识别/车牌识别RTSP/GB28181/SDK/Ehome协议视频平台EasyCVR搭建美丽乡村视频监控系统方案
    【操作说明】新版网络穿透+云端组网+远程运维+视频流拉转推平台EasyNTS上云网关管理平台如何安装?
    Windows/Android/iOS平台H265编码视频播放器EasyPlayerPro支持高码率视频播放和D3D画面旋转代码参考
    【操作说明】人脸识别/车牌识别系统视频智能分析平台EasyCVR如何配置开启HTTPS协议?
    程序员们 不要想一辈子靠技术混饭吃
    jsonObject的使用
    程序员们 不要想一辈子靠技术混饭吃
    从 iBatis 到 MyBatis
  • 原文地址:https://www.cnblogs.com/hxrlwq13/p/12803812.html
Copyright © 2011-2022 走看看