操作系统第四次实验报告:文件系统
- 姓名:倪晓东
- 学号:201821121020
- 班级:计算1811
1. 编写程序
在服务器上用Vim编写一个程序:实现Linux系统命令ls -lai
的功能,给出源代码。
源代码:
#include<stdio.h> 2 #include<sys/types.h> //基本系统数据类型头文件,含有size_t,time_t,pid_t等类型 3 #include<dirent.h> //为获取某文件目录内容 4 #include<sys/stat.h> //系统定义文件状态所在的伪标准头文件 5 #include<pwd.h> 6 #include<grp.h> 7 #include<unistd.h> 8 #include<string.h> 9 10 #define LS_NONE 0 //初始化参数 11 #define LS_L 101 12 #define LS_I 102 13 #define LS_A 200 14 #define LS_AL (LS_A+LS_L) 15 #define LS_AI (LS_A+LS_I) 16 #define LS_LAI (LS_L+LS_A+LS_I) 17 18 void show_file_info(char* filename,struct stat* info_p); 19 void mode_to_letters(int mode,char str[]); 20 char* uid_to_name(uid_t uid); 21 char* gid_to_name(gid_t gid); 22 void do_ls(char dirname[],int mode); 23 int analyzeparam(char* input); 24 25 int main(int ac,char* av[]){ 26 if(ac==1){ 27 do_ls(".",LS_NONE); 28 } 29 else{ 30 int mode=LS_NONE; 31 int have_file_param=0; 32 while(ac>1){ 33 ac--; 34 av++; 35 int calmode=analyzeparam(*av); 36 if(calmode!=-1){ 37 mode+=calmode; 38 } 39 else{ 40 have_file_param=1; 41 do{ 42 printf("%s:\n",*av); 43 do_ls(*av,mode); 44 printf("\n"); 45 ac--; 46 av++; 47 }while(ac>=1); 48 } 49 } 50 if(!have_file_param){ 51 do_ls(".",mode); 52 } 53 } 54 } 55 56 void show_file_info(char* filename,struct stat* info_p){ 57 char* uid_to_name(),*ctime(),*gid_to_name(),*filemode(); 58 void mode_to_letterts(); 59 char modestr[11]; 60 mode_to_letters(info_p->st_mode,modestr); 61 printf("%s",modestr); 62 printf(" %4d",(int)info_p->st_nlink); 63 printf(" %-8s",uid_to_name(info_p->st_uid)); 64 printf(" %-8s",gid_to_name(info_p->st_gid)); 65 printf(" %8ld",(long) info_p->st_size); 66 printf(" %.12s",4+ctime(&info_p->st_mtime)); 67 printf(" %s\n",filename); 68 } 69 void mode_to_letters(int mode,char str[]){ 70 strcpy(str,"--------"); 71 if(S_ISDIR(mode)){ 72 str[0]='d'; 73 } 74 if(S_ISCHR(mode)){ 75 str[0]='c'; 76 } 77 if(S_ISBLK(mode)){ 78 str[0]='b'; 79 } 80 if((mode &S_IRUSR)){ 81 str[1]='r'; 82 } 83 if((mode&S_IWUSR)){ 84 str[2]='w'; 85 } 86 if((mode&S_IXUSR)){ 87 str[3]='x'; 88 } 89 if((mode&S_IRGRP)){ 90 str[4]='r'; 91 } 92 if((mode&S_IWGRP)){ 93 str[5]='w'; 94 } 95 if((mode&S_IXGRP)){ 96 str[6]='x'; 97 } 98 if((mode&S_IROTH)){ 99 str[7]='r'; 100 } 101 if((mode&S_IWOTH)){ 102 str[8]='w'; 103 } 104 if((mode&S_IXOTH)){ 105 str[9]='x'; 106 } 107 } 108 char* uid_to_name(uid_t uid){ 109 struct passwd* getpwuid(),* pw_ptr; 110 static char numstr[10]; 111 if((pw_ptr=getpwuid(uid))==NULL){ 112 sprintf(numstr,"%d",uid); 113 return numstr; 114 } 115 else{ 116 return pw_ptr->pw_name; 117 } 118 } 119 char* gid_to_name(gid_t gid){ 120 struct group* getgrgid(),* grp_ptr; 121 static char numstr[10]; 122 if((grp_ptr=getgrgid(gid))==NULL){ 123 sprintf(numstr,"%d",gid); 124 return numstr; 125 } 126 else{ 127 return grp_ptr->gr_name; 128 } 129 } 130 int analyzeparam(char* input){ 131 if(strlen(input)==2){ 132 if(input[1]=='l')return LS_L; 133 if(input[1]=='a')return LS_A; 134 if(input[1]=='i')return LS_I; 135 } 136 else if(strlen(input)==3){ 137 if(input[1]=='a'&&input[2]=='l')return LS_AL; 138 if(input[1]=='a'&&input[2]=='i')return LS_AI; 139 } 140 else if(strlen(input)==4){ 141 if(input[1]=='l'&&input[2]=='a'&&input[3]=='i')return LS_LAI; 142 } 143 return -1; 144 } 145 void do_ls(char dirname[],int mode){ 146 DIR* dir_ptr; 147 struct dirent* direntp; 148 if((dir_ptr=opendir(dirname))==NULL){ 149 fprintf(stderr,"ls2:cannot open %s \n",dirname); 150 } 151 else{ 152 if(mode==LS_A){ 153 printf("%s\n",dirname); 154 } 155 else{ 156 char dirs[20][100]; 157 int dir_count=0; 158 while((direntp=readdir(dir_ptr))!=NULL){ 159 if(mode<200&&direntp->d_name[0]=='.'){ 160 continue; 161 } 162 char complete_d_name[200]; 163 strcpy (complete_d_name,dirname); 164 strcat (complete_d_name,"/"); 165 strcat (complete_d_name,direntp->d_name); 166 struct stat info; 167 if(stat(complete_d_name,&info)==-1){ 168 perror(complete_d_name); 169 } 170 else{ 171 if(mode==LS_L||mode==LS_AL){ 172 show_file_info(direntp->d_name,&info); 173 } 174 else if(mode==LS_A||mode==LS_NONE||mode==LS_I||mode==LS_AI){ 175 if(mode==LS_I||mode==LS_AI){ 176 printf("%llu ",direntp->d_ino); 177 } 178 printf("%s\n",direntp->d_name); 179 } 180 else if(mode==LS_LAI){ 181 printf("%llu ",direntp->d_ino); 182 show_file_info(direntp->d_name,&info); 183 } 184 } 185 } 186 } 187 closedir(dir_ptr); 188 } 189 }
2. 分析运行结果
给出运行结果截图,对于每一列是如何获取的,结合源代码做解释
运行结果:
使用命令ls -lai:
第1行:总计(total)
Total后面的数字是指当前目录下所有文件所占用的空间总和。在程序没有这个统计。
第1字段: 索引节点号
每行前面的数字组,一个索引节点号表示一个文件
实现代码:
printf("%llu "
, direntp->d_ino);
第2字段: 文件属性字段
每行第二个组成部分:,由10个字母组成;第一个字符代表文件的类型。
-:普通文件
d:目录文件
b:块设备文件
c:字符设备文件
l:符号链接文件
第1组的3个字符是授权文件所有者的权限;
第2组的3个字符是授权同组用户的权限;
第3组的3个字符是授权其他用户的权限。
每一组的3个字符一次表示读、写、执行权限,其中:
r:表示有读权限
w:表示有写权限
x:表示有执行权限
-:表示没有相应的权限
void mode_to_letters(int mode,char str[]){ 70 strcpy(str,"--------"); 71 if(S_ISDIR(mode)){ 72 str[0]='d'; 73 } 74 if(S_ISCHR(mode)){ 75 str[0]='c'; 76 } 77 if(S_ISBLK(mode)){ 78 str[0]='b'; 79 } 80 if((mode &S_IRUSR)){ 81 str[1]='r'; 82 } 83 if((mode&S_IWUSR)){ 84 str[2]='w'; 85 } 86 if((mode&S_IXUSR)){ 87 str[3]='x'; 88 } 89 if((mode&S_IRGRP)){ 90 str[4]='r'; 91 } 92 if((mode&S_IWGRP)){ 93 str[5]='w'; 94 } 95 if((mode&S_IXGRP)){ 96 str[6]='x'; 97 } 98 if((mode&S_IROTH)){ 99 str[7]='r'; 100 } 101 if((mode&S_IWOTH)){ 102 str[8]='w'; 103 } 104 if((mode&S_IXOTH)){ 105 str[9]='x'; 106 } 107 }
其中文件权限宏变量:
S_IRUSR //用户有读权限
S_IWUSR //用户有写权限
S_IXUSR //用户有执行权限
S_IRGRP //组有读权限
S_IWGRP //组有写权限
S_IXGRP //组有执行权限
S_IROTH //其他人有读权限
S_IWOTH //其他人有写权限
S_IXOTH //其他人有可执行权限
第3字段:文件硬链接数
该字段表示文件的硬链接数,如果是一个目录,则表示该目录下子目录的个数
实现代码:printf(" %4d"
, (
int
) info_p->st_nlink);
第4字段:文件(目录)拥有者
该字段表示这个文件的拥有者
实现代码:
char* uid_to_name(uid_t uid)
第5字段:文件(目录)拥有者所在的组
拥有者可以加入多个组,一个主组
实现代码:
char* gid_to_name(gid_t gid)
第6字段: 文件所占用的空间(以字节为单位)
该字段表示当前文件或者文件夹大小
实现代码:
printf(" %8ld", (long) info_p->st_size);
第7字段:文件(目录)最近访问(修改)时间
该字段表示该文件最近一次修改时间
实现代码:
printf(" %.12s", 4 + ctime(&info_p->st_mtime));
第8字段:文件名
实现代码:
printf(" %s\n", filename);
Linux ls命令:
-A列出所有条目,除了.(点)和..(点-点)
-i显示每个文件报告第一列中的索引节点数目
-l(显示方式、链接数目、所有者、组、大小(按字节)和每个文件最近一次修改时间
3.参考资料:
https://www.cnblogs.com/fakerli/p/12105440.html