您的位置:首页 > 运维架构 > Linux

Understanding Unix/Linux Programming-ls指令练习二

2016-08-26 18:13 399 查看
完善ls练习一的功能:排序,使用qsort

分栏,计算宽度和行数

文件“.”的显示需要由-a选项来选择

详细信息的显示,-l选项

将stat结构体中的st_mode——16位二进制数转换成10位的字符串
15-12:type

11:suid

10:sgid

9:sticky

8-6:user

5-3:group

2-0:other

/etc/passwd文件中包含了用户信息,每行对应一个用户,不同的属性按照分号‘:’隔开。
该文件并未包含所有的用户,在某些网络计算系统中,用户需要登录到任何一台主机上,会有NIS统一地进行身份验证,本地保存的只是一个用户子集。

getpwuid系统调用具有较好的可移植性,会从NIS中查找如果在本地找不到的话

/etc/group包含了组信息,字段分别为1,组名;2,组密码;3,组ID;4,组成员列表
一个用户可以属于多个组的

getgrgid可以用来访问组列表,移植性同上getpwuid

1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <dirent.h>
5 #include <pwd.h>
6 #include <grp.h>
7 #include <string.h>
8 #include <time.h>
9
10 void do_ls(char[]);
11 void show_file_info(char * filename , struct stat * statbufp );
12 void mode2letter(int mode , char str[]);
13 void print_uid2name(uid_t uid );
14 void print_gid2name(gid_t gid );
15
16 int main(int ac , char * av[])
17 {
18     if(ac == 1 )
19     {
20         do_ls(".");
21     }
22     else
23     {
24         while( -- ac )
25         {
26             printf("%s:\n", * (++ av) );
27             do_ls(*av);
28         }
29     }
30     return 0 ;
31 }
32
33 void do_ls(char dirname[])
34 {
35     DIR * dir_ptr ;
36     struct dirent * direntp ;
37     struct stat statbuf ;
38
39     if( ( dir_ptr = opendir(dirname) )== NULL )
40     {
41         fprintf(stderr, "ls1 can not open %s\n", dirname );
42     }
43     else
44     {
45         while( ( direntp = readdir(dir_ptr ) ) != NULL )
46         {
47             if( stat(direntp -> d_name , &statbuf) == -1 )
48             {
49                 perror(direntp -> d_name );
50             }
51             else
52             {
53                 show_file_info( direntp -> d_name , &statbuf);
54             }
55         }
56     }
57
58     closedir(dir_ptr);
59 }
60
61 void show_file_info( char * filename, struct stat * statbufp )
62 {
63     char modestr[11]; // include '\0' so 10 + 1 = 11
64
65     mode2letter(statbufp -> st_mode , modestr) ;
66     printf("%s",  modestr );
67
68     printf("%4d", (int)statbufp -> st_nlink ) ;
69     print_uid2name( statbufp -> st_uid ) ;
70     print_gid2name( statbufp -> st_gid ) ;
71     printf("%8ld", (long) (statbufp -> st_size) );
72     printf(" %12.12s", (char*)(4 + ctime(&(statbufp -> st_mtime)) ));
73     printf(" %s\n",filename );
74 }
75
76 void mode2letter(int mode , char str[])
77 {
78     strcpy(str , "----------");
79
80     if( S_ISDIR( mode ))
81         str[0] = 'd' ;
82     else if( S_ISCHR( mode ))
83         str[0] = 'c' ;    // else for efficience
84     else if( S_ISBLK( mode ))
85         str[0] = 'b' ;
86
87     if( mode & S_IRUSR )
88         str[1] = 'r' ;
89     if( mode & S_IWUSR )
90         str[2] = 'w' ;
91     if(mode & S_IXUSR )
92         str[3] = 'x' ;
93
94     if( mode & S_IRGRP )
95         str[4] = 'r' ;
96     if( mode & S_IWGRP )
97         str[5] = 'w' ;
98     if( mode & S_IXGRP )
99         str[6] = 'x' ;
100
101     if( mode & S_IROTH )
102         str[7] = 'r' ;
103     if( mode & S_IWOTH )
104         str[8] = 'w' ;
105     if( mode & S_IXOTH )
106         str[9] = 'x' ;
107 }
108
109 void print_uid2name( uid_t uid )
110 {
111     struct passwd * passwdbufp ;
112
113     if(( passwdbufp = getpwuid(uid)) != (struct passwd *)NULL ) // Except for error
114     {
115         printf( "%-8s" , passwdbufp -> pw_name ) ;
116     }
117     else
118     {
119         printf( "%8d" , uid) ;
120     }
121
122 }
123
124 void print_gid2name(gid_t gid)
125 {
126     struct group * grp_ptr ;
127     if(( grp_ptr = getgrgid(gid)) != (struct group * )NULL )
128     {
129         printf("%-8s" , grp_ptr -> gr_name ) ;
130     }
131     else
132     {
133         printf("%8d" , gid ) ;
134     }
135 }


 

ls2.c完成了 ls -l 的功能。但是有几点不足之处:

不显示总数,这个容易解决

未排序

不支持参数-a

假设参数只是目录名

不能显示指定目录的信息

以上代码在OpenSuse Leap42.1上测试通过,参考原书《Unix/Linux编程实践教程》,但是含有个人修改部分,不影响功能。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐