操作系统第4次实验报告:文件系统

  • 姓名:吕煜华
  • 学号:201821121046
  • 班级:计算1812

1. 编写程序

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

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<string.h>
  4 #include<unistd.h>
  5 #include<dirent.h>
  6 #include<sys/stat.h>
  7 #include<sys/types.h>
  8 #include<time.h>
  9 #include<fcntl.h>
 10 #include<pwd.h>
 11 #include<grp.h>
 12
 13 void error_printf(const char*);
 14 void list_dir(const char*);
 15 void list_message(const char*, const struct stat*);
 16 void file_type(const struct stat*);
 17 void file_power(const struct stat*);
 18 void file_id(const struct stat*);
 19 void file_mtime(const struct stat*);
 20 void link_printf(const char*);
 21
 22 void error_printf(const char* funname){
 23     perror(funname);
 24     exit(1);
 25 }
 26
 27 void list_dir(const char* pathname){
 28     DIR* ret_opendir = opendir(pathname); //打开目录
 29     if(ret_opendir == NULL)
 30         error_printf("opendir");
 31
 32     int ret_chdir = chdir(pathname);  //转到”pathname“,便于stat函数的使用
 33     if(ret_chdir == -1)
 34         error_printf("chdir");
 35
 36     struct dirent* ret_readdir =NULL;
 37     while(ret_readdir = readdir(ret_opendir))
 38     {
 39         char* filename = ret_readdir->d_name;  //获取文件名
 40         struct stat file_message ={};
 41         int ret_stat = lstat(filename, &file_message); //获取文件信息
 42         if(ret_stat == -1)
 43             printf("%s error!", filename);
 44         else if(strcmp(filename,".") && strcmp(filename, ".."))
 45             list_message(filename, &file_message);
 46     }
 47 }
 48
 49 void list_message(const char* filename, const struct stat* file_message){
 50     file_type(file_message); // 判断打印类型
 51
 52     printf("%d ",(int)file_message->st_ino); //添加索引号
 53     file_power(file_message); //判断并打印文件权限
 54     printf("%3ld ",file_message->st_nlink); //打印硬链接数
 55     file_id(file_message); //转换并打印用户id与组id
 56     printf("%5ld ", file_message->st_size);  //打印文件大小
 57     file_mtime(file_message);  //打印文件最后修改时间
 58     printf("%s ", filename);  //打印文件名
 59     if(S_ISLNK(file_message->st_mode))  //如果是软链接文件打印其指向的位置
 60         link_printf(filename);
 61     puts("");
 62 }
 63
 64 void file_type(const struct stat* file_message){
 65     mode_t mode = file_message->st_mode;
 66
 67     if(S_ISREG(mode))        printf("-"); //普通文件
 68     else if(S_ISDIR(mode))   printf("d"); //目录文件
 69     else if(S_ISCHR(mode))   printf("c"); //字符设备文件
 70     else if(S_ISBLK(mode))   printf("b"); //块设备文件
 71     else if(S_ISFIFO(mode))  printf("p"); //管道文件
 72     else if(S_ISLNK(mode))   printf("l"); //链接文件
 73     else                     printf("s"); //socket文件
 74 }
 75
 76 void file_power(const struct stat* file_message){
 77     mode_t mode = file_message->st_mode;
 78
 79     printf("%c", mode&S_IRUSR?'r':'-');
 80     printf("%c", mode&S_IWUSR?'w':'-');
 81     printf("%c", mode&S_IXUSR?'x':'-');
 82
 83     printf("%c", mode&S_IRGRP?'r':'-');
 84     printf("%c", mode&S_IWGRP?'w':'-');
  85     printf("%c", mode&S_IXGRP?'x':'-');
 86
 87     printf("%c", mode&S_IROTH?'r':'-');
 88     printf("%C", mode&S_IWOTH?'w':'-');
 89     printf("%c ", mode&S_IXOTH?'x':'-');
 90 }
 91
 92 void file_id(const struct stat* file_message){
 93     struct passwd* pwd;
 94     pwd = getpwuid(file_message->st_uid);
 95     printf("%s ", pwd->pw_name);
 96
 97     struct group* grp;
 98     grp = getgrgid(file_message->st_gid);
 99     printf("%s ", grp->gr_name);
100 }
101
102 void file_mtime(const struct stat* file_message){
103     struct tm* t = localtime(&file_message->st_mtime);
104     printf("%2d月%2d日 %2d:%2d ", t->tm_mon+1, t->tm_mday, t->tm_hour, t->tm    _min);
 105 }
106
107 void link_printf(const char* filename){
108     char buf[1024] = "123";
109     if(0 == readlink(filename, buf, sizeof(buf)))
110         error_printf("readlink");
111     printf("-> %s ", buf);
112 }
113
114 int main()
115 {
116     char path[1024] = {};
117     strcpy(path, "./");
118     struct stat file_message={};
119
120     int ret_stat = lstat(path, &file_message);
121     if(ret_stat == -1)
122         error_printf("stat");
123
124     if(S_ISDIR(file_message.st_mode))  //判断是否为目录
125         list_dir(path);
126     else
127         list_message(path, &file_message);
128     return 0;
129 }
130
                                               

 

2. 分析运行结果

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

 

 

 

分析结果如下:

(1)第一列为文件索引号

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

 

(2)第二列首字母为文件类型,后面的 “r” 、“w”、“x”为读、写、执行的权限。

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':'-');
}

 

(3)第三列为文件硬链接个数

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

 

(4)第四列为文件用户信息

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

 

(5)第五列为文件用户组信息

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

 

(6)第六列为文件大小

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

 

(7)第七列为文件上次修改的时间

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); // 打印文件上次修改的时间
}

 

(8)第八列为文件名

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

 

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

了解了ls -lai

ls -l   #以长格式显示目录下的内容列表。输出的信息从左到右依次包括文件名,文件类型、权限模式、硬连接数、所有者、组、文件大小和文件的最后修改时间等
ls -a   #显示所有档案及目录(ls内定将档案名或目录名称为“.”的视为隐藏,不会列出)
ls -i   #显示文件索引节点号(inode number),一个索引节点代表一个文件
posted @ 2020-04-30 22:00  Lvyuhua  阅读(474)  评论(0编辑  收藏  举报