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

  • 姓名:白晓
  • 学号:201821121035
  • 班级:计算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<fcntl.h>
  9 #include<time.h>
 10 #include<pwd.h>
 11 #include<grp.h>
 12 
 13 #define PARAMETER_NONE 0 
 14 #define PARAMETER_A 1 
 15 #define PARAMETER_L 2 
 16 #define MAXROWLEN 80 
 17 int g_leave_len = MAXROWLEN; 
 18 int g_maxlen; 
 19 void error(const char *err_string, int line); 
 20 void Demonstrate_attribute(struct stat buf, char * name);
 21 void Demonstrate_single(char * name);
 22 void Demonstrate(int flag, char * pathname); /
 23 void Demonstrate_dir(int flag_parameter, char * path); 
 24 
 25 int main(int argc, char ** argv){
 26 int i, j, k, num;
 27 char path[PATH_MAX+1]; //文件路径名
 28 char parameter[32]; // 保存命令行参数
 29 int flag_parameter = PARAMETER_NONE; // 用来标志参数种类
 30 struct stat buf;
 31 j = 0,
 32 num = 0;
 33 for (i = 1 ; i < argc; i++){
 34 if (argv[i][0] == '-'){
 35 for(k = 1; k < strlen(argv[i]); k++){
 36 parameter[j] = argv[i][k]; // 获取-后面的参数保存到数组parameter中
 37 j++;
 38 }
 39 num++; // 保存"-"的个数
 40 }
 41 }
 42 for(i = 0; i < j; i++){
 43 if (parameter[i] == 'a'){
 44 flag_parameter = PARAMETER_A;
 45 continue;
 46 }
 47 else if (parameter[i] == 'l'){
 48 flag_parameter = PARAMETER_L;
 49 continue;
 50 }
 51 else{
 52 printf("my_ls: invalid option -%c\n", parameter[i]);
 53 exit(1);
 54 }
 55 }
 56 parameter[j] = '\0';
 57 if ((num + 1) == argc){
 58 strcpy(path, "./");// "./"当前目录
 59 path[2] = '\0';
 60 Demonstrate_dir(flag_parameter, path);
 61 return 0;
 62 }
 63 i=1;
 64 do {
 65 if (argv[i][0] == '-'){
 66 i++;
 67 continue;
 68 }
 69 else{
 70 strcpy(path, argv[i]);
 71 if ( stat(path, &buf) == -1 ){
 72 error("stat", __LINE__);
 73 }
 74 if ( S_ISDIR(buf.st_mode) ) // argv[i]是一个目录{
 75 if ( path[ strlen(argv[i])-1 ] != '/'){
 76 path[ strlen(argv[i]) ] = '/';
 77 path[ strlen(argv[i])+1 ] = '\0';
 78 }
 79 else{
 80 path[ strlen(argv[i]) ] = '\0';
 81 }
 82 Demonstrate_dir(flag_parameter,path);
 83 i++;
 84 }
 85 else{
 86 Demonstrate(flag_parameter, path);
 87 i++;
 88 }
 89 }
 90 } while (i < argc);
 91 return 0;
 92 }
 93 void error(const char *err_string, int line){
 94 fprintf(stderr, "line:%d ", line);
 95 perror(err_string);
 96 exit(1);
 97 }
 98 void Demonstrate_attribute(struct stat buf, char * name){
 99 char buf_time[32]; //存放时间
100 struct passwd *psd; //从该结构体中获取文件所有者的用户名
101 struct group *grp; //从该结构体中获取文件所有者所属组的组名
102 if (S_ISLNK(buf.st_mode)){
103 printf("l");
104 }
105 else if (S_ISREG(buf.st_mode)){
106 printf("-");
107 }
108 else if (S_ISDIR(buf.st_mode)){
109 printf("d");
110 }
111 else if (S_ISCHR(buf.st_mode)){
112 printf("c");
113 }
114 else if (S_ISBLK(buf.st_mode)){
115 printf("b");
116 }
117 else if (S_ISFIFO(buf.st_mode)){
118 printf("f");
119 }
120 else if (S_ISSOCK(buf.st_mode)){
121 printf("s");
122 }
123 if (buf.st_mode & S_IRUSR){
124 printf("r");
125 }
126 else{
127 printf("-");
128 }
129 if (buf.st_mode & S_IWUSR){
130 printf("w");
131 }
132 else{
133 printf("-");
134 }
135 if (buf.st_mode & S_IXUSR){
136 printf("x");
137 }
138 else{
139 printf("-");
140 }
141 if (buf.st_mode & S_IRGRP){
142 printf("r");
143 }
144 else{
145 printf("-");
146 }
147 if (buf.st_mode & S_IWGRP)
148 {
149 printf("w");
150 }
151 else{
152 printf("-");
153 }
154 if (buf.st_mode & S_IXGRP){
155 printf("x");
156 }
157 else{
158 printf("-");
159 }
160 if (buf.st_mode & S_IROTH){
161 printf("r");
162 }
163 else{
164 printf("-");
165 }
166 if (buf.st_mode & S_IWOTH){
167 printf("w");
168 }
169 else
170 {
171 printf("-");
172 }
173 if (buf.st_mode & S_IXOTH){
174 printf("x");
175 }
176 else{
177 printf("-");
178 }
179 printf(" ");
180 psd = getpwuid(buf.st_uid);
181 grp = getgrgid(buf.st_gid);
182 printf("%4d ",buf.st_nlink); //打印文件的链接数
183 printf("%-9s", psd->pw_name); //打印文件拥有者
184 printf("%-8s", grp->gr_name); //打印文件所属用户组
185 printf("%6d",(int)buf.st_size); // 打印文件的大小
186 strcpy(buf_time, ctime(&buf.st_mtime));
187 buf_time[strlen(buf_time) - 1] = '\0'; // 去掉换行符
188 printf(" %s", buf_time); // 打印文件的时间信息
189 }
190 void Demonstrate_single(char *name){
191 int i, len;
192 if (g_leave_len < g_maxlen){
193 printf("\n");
194 g_leave_len = MAXROWLEN;
195 }
196 len = strlen(name);
197 len = g_maxlen - len;
198 printf("%-s", name);
199 for (i = 0; i < len; i++){
200 printf(" ");
201 }
202 printf(" ");
203 g_leave_len -= (g_maxlen + 2);
204 }
205 void Demonstrate(int flag, char * pathname){
206 int i, j;
207 struct stat buf;
208 char name[NAME_MAX + 1];
209 for (i = 0, j = 0; i < strlen(pathname); i++){
210 if (pathname[i] == '/'){
211 j = 0;
212 continue;
213 }
214 name[j++] = pathname[i];
215 }
216 name[j] = '\0';
217 if ( lstat(pathname, &buf) == -1 ){
218 error("stat", __LINE__);
219 }
220 switch (flag){
221 case PARAMETER_NONE: // 没有-l和-a选项
222 if (name[0] != '.'){
223 Demonstrate_single(name);
224 }
225 break;
226 case PARAMETER_A: // -a:显示包括隐藏文件在内的所有文件
227 Demonstrate_single(name);
228 break;
229 case PARAMETER_L: // -l:每个文件单独占一行,显示文件的详细属性信息
230 if (name[0] != '.'){
231 Demonstrate_attribute(buf, name);
232 printf(" %-s\n", name);
233 }
234 break;
235 case PARAMETER_A + PARAMETER_L: // 同时有-a和-l选项的情况
236 Demonstrate_attribute(buf, name);
237 printf(" %-s\n", name);
238 break;
239 default:
240 break;
241 }
242 }
243 void Demonstrate_dir(int flag_parameter, char *path){
244 DIR *dir;
245 struct dirent *ptr;
246 int count = 0;
247 char filenames[256][PATH_MAX + 1],temp[PATH_MAX + 1];// 获取该目录下文件总数和最长的文件名
248 dir = opendir(path);
249 if (dir == NULL){
250 error("opendir", __LINE__);
251 }
252 while ((ptr = readdir(dir)) != NULL){
253 if (g_maxlen < strlen(ptr->d_name))
254 g_maxlen = strlen(ptr->d_name);
255 count++;
256 }
257 closedir(dir);
258 if(count > 256)
259 error("too many files under this dir",__LINE__);
260 int i, j, len = strlen(path);// 获取该目录下所有的文件名
261 dir = opendir(path);
262 for(i = 0; i < count; i++){
263 ptr = readdir(dir);
264 if( ptr == NULL){
265 error("readdir",__LINE__);
266 }
267 strncpy(filenames[i],path,len); //filenames存放目录下的所有文件名
268 filenames[i][len] = '\0';
269 strcat(filenames[i],ptr->d_name);
270 filenames[i][len + strlen(ptr->d_name)] = '\0';
271 }
272 for(i = 0; i < count-1; i++)
273 for(j = 0; j < count - 1 - i; j++)
274 {
275 if( strcmp(filenames[j],filenames[j + 1]) > 0 )
276 {
277 strcpy(temp,filenames[j + 1]);
278 temp[strlen(filenames[j + 1])] = '\0';
279 strcpy(filenames[j + 1],filenames[j]);
280 filenames[j + 1][strlen(filenames[j])] = '\0';
281 strcpy(filenames[j], temp);
282 filenames[j][strlen(temp)] = '\0';
283 }
284 }
285 for(i = 0; i < count; i++)
286 Demonstrate(flag_parameter, filenames[i]);
287 closedir(dir);
288 if( (flag_parameter & PARAMETER_L) == 0)
289 printf("\n");
290 }

 

2. 分析运行结果

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

获取文件权限:

 1 if (S_ISLNK(buf.st_mode)){
 2 printf("l");
 3 }
 4 else if (S_ISREG(buf.st_mode)){
 5 printf("-");
 6 }
 7 else if (S_ISDIR(buf.st_mode)){
 8 printf("d");
 9 }
10 else if (S_ISCHR(buf.st_mode)){
11 printf("c");
12 }
13 else if (S_ISBLK(buf.st_mode)){
14 printf("b");
15 }
16 else if (S_ISFIFO(buf.st_mode)){
17 printf("f");
18 }
19 else if (S_ISSOCK(buf.st_mode)){
20 printf("s");
21 }
22 if (buf.st_mode & S_IRUSR){
23 printf("r");
24 }
25 else{
26 printf("-");
27 }
28 if (buf.st_mode & S_IWUSR){
29 printf("w");
30 }
31 else{
32 printf("-");
33 }
34 if (buf.st_mode & S_IXUSR){
35 printf("x");
36 }
37 else{
38 printf("-");
39 }
40 if (buf.st_mode & S_IRGRP){
41 printf("r");
42 }
43 else{
44 printf("-");
45 }
46 if (buf.st_mode & S_IWGRP)
47 {
48 printf("w");
49 }
50 else{
51 printf("-");
52 }
53 if (buf.st_mode & S_IXGRP){
54 printf("x");
55 }
56 else{
57 printf("-");
58 }
59 if (buf.st_mode & S_IROTH){
60 printf("r");
61 }
62 else{
63 printf("-");
64 }
65 if (buf.st_mode & S_IWOTH){
66 printf("w");
67 }
68 else
69 {
70 printf("-");
71 }
72 if (buf.st_mode & S_IXOTH){
73 printf("x");
74 }
75 else{
76 printf("-");
77 }

文件的大小、文件最后的修改时间、文件名:

1 printf("%4d ",buf.st_nlink); //打印文件的链接数
2 printf("%-9s", psd->pw_name); //打印文件拥有者
3 printf("%-8s", grp->gr_name); //打印文件所属用户组
4 printf("%6d",(int)buf.st_size); // 打印文件的大小
5 strcpy(buf_time, ctime(&buf.st_mtime));
6 buf_time[strlen(buf_time) - 1] = '\0'; // 去掉换行符
7 printf(" %s", buf_time); // 打印文件的时间信息

 

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

opendir:DIR *opendir(const char *name), 传文件名,返回一个指针,指向目录序列

readdir:struct dirent *readdir(DIR *dirp), 把opendir的返回值传过来, 返回值为一个结构体

posted @ 2020-04-30 21:05  木澈  阅读(196)  评论(0编辑  收藏  举报