Mercurial > hg > toybox
comparison toys/pending/stat.c @ 872:793972c94560
stat cleanup
author | Felix Janda <felix.janda@posteo.de> |
---|---|
date | Sat, 20 Apr 2013 00:18:17 +0200 |
parents | 8aa07b575cd6 |
children | beb32d780164 |
comparison
equal
deleted
inserted
replaced
871:8aa07b575cd6 | 872:793972c94560 |
---|---|
1 /* stat.c : display file or file system status | 1 /* stat.c : display file or file system status |
2 * anand.sinha85@gmail.com | 2 * anand.sinha85@gmail.com |
3 * Copyright 2012 <warior.linux@gmail.com> | 3 * Copyright 2012 <warior.linux@gmail.com> |
4 | 4 |
5 USE_STAT(NEWTOY(stat, "LZfc", TOYFLAG_BIN)) | 5 USE_STAT(NEWTOY(stat, "LZc:f", TOYFLAG_BIN)) |
6 | 6 |
7 config STAT | 7 config STAT |
8 bool stat | 8 bool stat |
9 default n | 9 default n |
10 help | 10 help |
46 */ | 46 */ |
47 | 47 |
48 #define FOR_stat | 48 #define FOR_stat |
49 #include "toys.h" | 49 #include "toys.h" |
50 | 50 |
51 #define SIZE_DATE_TIME_STAT 36 | |
52 #define access_string(x, s, i) if((x&7) & 1) \ | |
53 s[9 - i * 3] = 'x'; \ | |
54 else \ | |
55 s[9 - i * 3] = '-'; \ | |
56 if(((x&7) >> 1) & 1) \ | |
57 s[9 - (i * 3 + 1)] = 'w'; \ | |
58 else \ | |
59 s[9 - (i * 3 + 1)] = '-'; \ | |
60 if(((x&7) >> 2) & 1) \ | |
61 s[9 - (i * 3 + 2)] = 'r'; \ | |
62 else \ | |
63 s[9 - (i * 3 + 2)] = '-'; | |
64 | |
65 static char *check_type_file(mode_t, size_t); | |
66 static char *get_access_str(unsigned long, mode_t); | |
67 static char *date_stat_format(time_t ); | |
68 inline void print_stat_format(char *, int); | |
69 | |
70 GLOBALS( | 51 GLOBALS( |
52 char *fmt; | |
71 char *access_str; | 53 char *access_str; |
72 char *file_type; | 54 char *file_type; |
73 struct passwd *user_name; | 55 struct passwd *user_name; |
74 struct group *group_name; | 56 struct group *group_name; |
75 struct tm *time_toy; | |
76 struct stat *toystat; | 57 struct stat *toystat; |
77 struct statfs *toystatfs; | 58 struct statfs *toystatfs; |
78 int toy_obj_file_arg; | |
79 ) | 59 ) |
80 | 60 |
81 | 61 |
82 static void do_stat(const char * file_name) | 62 static void do_stat(const char * file_name) |
83 { | 63 { |
84 TT.toystat = xmalloc(sizeof(struct stat)); | 64 TT.toystat = xmalloc(sizeof(struct stat)); |
85 if (stat(file_name, TT.toystat) < 0) perror_msg("stat: '%s'", file_name); | 65 if (stat(file_name, TT.toystat) < 0) perror_exit("stat: '%s'", file_name); |
86 } | 66 } |
87 | 67 |
88 static void do_statfs(const char * file_name) | 68 static void do_statfs(const char * file_name) |
89 { | 69 { |
90 TT.toystatfs = xmalloc(sizeof(struct statfs)); | 70 TT.toystatfs = xmalloc(sizeof(struct statfs)); |
91 if (statfs(file_name, TT.toystatfs) < 0) | 71 if (statfs(file_name, TT.toystatfs) < 0) |
92 perror_msg("statfs: '%s'", file_name); | 72 perror_exit("statfs: '%s'", file_name); |
93 } | 73 } |
94 | 74 |
95 static char * check_type_file(mode_t mode, size_t size) | 75 static char * check_type_file(mode_t mode, size_t size) |
96 { | 76 { |
97 if (S_ISREG(mode)) { | 77 if (S_ISREG(mode)) { |
104 if (S_ISFIFO(mode)) return "FIFO (named pipe)"; | 84 if (S_ISFIFO(mode)) return "FIFO (named pipe)"; |
105 if (S_ISLNK(mode)) return "symbolic link"; | 85 if (S_ISLNK(mode)) return "symbolic link"; |
106 if (S_ISSOCK(mode)) return "socket"; | 86 if (S_ISSOCK(mode)) return "socket"; |
107 } | 87 } |
108 | 88 |
109 static char * get_access_str(unsigned long pernission, mode_t mode) | 89 static char * get_access_str(unsigned long permission, mode_t mode) |
110 { | 90 { |
111 static char access_string[10]; | 91 static char access_string[11]; |
112 int i; | 92 char *s = access_string; |
113 | 93 char *rwx[] = {"---", "--x", "-w-", "-wx", |
114 if (S_ISDIR(mode)) access_string[0] = 'd'; | 94 "r--", "r-x", "rw-", "rwx"}; |
115 else access_string[0] = '-'; | 95 |
116 for (i = 0; i < 3; i++) | 96 if (S_ISDIR(mode)) *s = 'd'; |
117 access_string(pernission >> (i * 3) & 7, access_string, i); | 97 else *s = '-'; |
98 | |
99 for (s += 7; s > access_string; s-=3) { | |
100 memcpy(s, rwx[permission & 7], 3); | |
101 permission >>= 3; | |
102 } | |
118 | 103 |
119 access_string[10] = '\0'; | 104 access_string[10] = '\0'; |
120 return access_string; | 105 return access_string; |
121 } | 106 } |
122 | 107 |
123 static char * date_stat_format(time_t time) | 108 static char * date_stat_format(time_t time) |
124 { | 109 { |
125 static char buf[SIZE_DATE_TIME_STAT]; | 110 static char buf[36]; |
126 | 111 |
127 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S.000000000", localtime(&time)); | 112 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S.000000000", localtime(&time)); |
128 return buf; | 113 return buf; |
129 } | 114 } |
130 | 115 |
131 inline void print_stat_format(char *format, int flag) | 116 static void print_stat_format(char *format, int flag) |
132 { | 117 { |
133 format++; | 118 for (; *format; format++) { |
134 switch (*format) { | 119 if (*format != '%') { |
135 case 'a': | 120 xprintf("%c", *format); |
136 if (flag) xprintf("%lu\n", TT.toystatfs->f_bavail); | 121 continue; |
137 else xprintf("%04lo\n",TT.toystat->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)); | |
138 break; | |
139 case 'A': | |
140 xprintf("%s\n",TT.access_str); | |
141 break; | |
142 case 'b': | |
143 if (flag) xprintf("%lu\n", TT.toystatfs->f_blocks); | |
144 else xprintf("%llu\n", TT.toystat->st_blocks); | |
145 break; | |
146 case 'B': | |
147 xprintf("%lu\n", TT.toystat->st_blksize); | |
148 break; | |
149 case 'c': | |
150 if (flag) xprintf("%lu\n", TT.toystatfs->f_files); | |
151 break; | |
152 case 'C': | |
153 xprintf("Currently feature is not supported\n"); | |
154 break; | |
155 case 'd': | |
156 if (flag) xprintf("%lu\n", TT.toystatfs->f_ffree); | |
157 else xprintf("%ldd\n", TT.toystat->st_dev); | |
158 break; | |
159 case 'D': | |
160 xprintf("%llxh\n", TT.toystat->st_dev); | |
161 break; | |
162 case 'f': | |
163 if (flag) xprintf("%lu\n", TT.toystatfs->f_bfree); | |
164 else xprintf("%lx\n", TT.toystat->st_mode); | |
165 break; | |
166 case 'F': | |
167 xprintf("%s\n", TT.file_type); | |
168 break; | |
169 case 'g': | |
170 xprintf("%lu\n", TT.toystat->st_uid); | |
171 break; | |
172 case 'G': | |
173 xprintf("%8s\n", TT.user_name->pw_name); | |
174 break; | |
175 case 'h': | |
176 xprintf("%lu\n", TT.toystat->st_nlink); | |
177 break; | |
178 case 'i': | |
179 if (flag) | |
180 xprintf("%d%d\n", TT.toystatfs->f_fsid.__val[0], TT.toystatfs->f_fsid.__val[1]); | |
181 else xprintf("%llu\n", TT.toystat->st_ino); | |
182 break; | |
183 case 'l': | |
184 if (flag) xprintf("need to implement\n"); | |
185 break; | |
186 case 'n': | |
187 xprintf("%s\n", toys.optargs[TT.toy_obj_file_arg]); | |
188 break; | |
189 case 'N': | |
190 xprintf("`%s\n'", toys.optargs[TT.toy_obj_file_arg]); | |
191 break; | |
192 case 'o': | |
193 xprintf("%lu\n", TT.toystat->st_blksize); | |
194 break; | |
195 case 's': | |
196 if (flag) xprintf("%d\n", TT.toystatfs->f_frsize); | |
197 else xprintf("%llu\n", TT.toystat->st_size); | |
198 break; | |
199 case 'S': | |
200 if (flag) xprintf("%d\n", TT.toystatfs->f_bsize); | |
201 break; | |
202 case 't': | |
203 if (flag) xprintf("%lx\n", TT.toystatfs->f_type); | |
204 break; | |
205 case 'T': | |
206 if (flag) xprintf("Needs to be implemented\n"); | |
207 break; | |
208 case 'u': | |
209 xprintf("%lu\n", TT.toystat->st_uid); | |
210 break; | |
211 case 'U': | |
212 xprintf("%8s\n", TT.user_name->pw_name); | |
213 break; | |
214 case 'x': | |
215 xprintf("%s\n", date_stat_format(TT.toystat->st_atime)); | |
216 break; | |
217 case 'X': | |
218 xprintf("%llu\n", TT.toystat->st_atime); | |
219 break; | |
220 case 'y': | |
221 xprintf("%s\n", date_stat_format(TT.toystat->st_mtime)); | |
222 break; | |
223 case 'Y': | |
224 xprintf("%llu\n", TT.toystat->st_mtime); | |
225 break; | |
226 case 'z': | |
227 xprintf("%s\n", date_stat_format(TT.toystat->st_ctime)); | |
228 break; | |
229 case 'Z': | |
230 xprintf("%llu\n", TT.toystat->st_ctime); | |
231 default: | |
232 xprintf("%c\n", *format); | |
233 break; | |
234 } | |
235 exit(0); | |
236 } | |
237 | |
238 void stat_main(void) | |
239 { | |
240 int stat_flag_Z = 0, stat_flag_f = 0, stat_flag_c = 0, stat_format = 0; | |
241 | |
242 if (toys.optargs) { | |
243 if (toys.optflags & 1) { | |
244 stat_flag_c = 1; | |
245 TT.toy_obj_file_arg = 1; | |
246 stat_format = 1; | |
247 } | 122 } |
248 if (toys.optflags & (1 << 1)) { | 123 format++; |
249 stat_flag_f = 1; | 124 switch (*format) { |
250 do_statfs(toys.optargs[TT.toy_obj_file_arg]); | 125 case 'a': |
251 } else do_stat(toys.optargs[TT.toy_obj_file_arg]); | 126 if (flag) xprintf("%lu", TT.toystatfs->f_bavail); |
252 if (toys.optflags & (1 << 2)) { | 127 else xprintf("%04lo",TT.toystat->st_mode & ~S_IFMT); |
253 stat_flag_Z = 1; | 128 break; |
254 xprintf("SELinux feature has not been implemented so far..\n"); | 129 case 'A': |
130 xprintf("%s",TT.access_str); | |
131 break; | |
132 case 'b': | |
133 if (flag) xprintf("%lu", TT.toystatfs->f_blocks); | |
134 else xprintf("%llu", TT.toystat->st_blocks); | |
135 break; | |
136 case 'B': | |
137 xprintf("%lu", TT.toystat->st_blksize); | |
138 break; | |
139 case 'c': | |
140 if (flag) xprintf("%lu", TT.toystatfs->f_files); | |
141 break; | |
142 case 'C': | |
143 xprintf("Currently feature is not supported"); | |
144 break; | |
145 case 'd': | |
146 if (flag) xprintf("%lu", TT.toystatfs->f_ffree); | |
147 else xprintf("%ldd", TT.toystat->st_dev); | |
148 break; | |
149 case 'D': | |
150 xprintf("%llxh", TT.toystat->st_dev); | |
151 break; | |
152 case 'f': | |
153 if (flag) xprintf("%lu", TT.toystatfs->f_bfree); | |
154 else xprintf("%lx", TT.toystat->st_mode); | |
155 break; | |
156 case 'F': | |
157 xprintf("%s", TT.file_type); | |
158 break; | |
159 case 'g': | |
160 xprintf("%lu", TT.toystat->st_uid); | |
161 break; | |
162 case 'G': | |
163 xprintf("%8s", TT.user_name->pw_name); | |
164 break; | |
165 case 'h': | |
166 xprintf("%lu", TT.toystat->st_nlink); | |
167 break; | |
168 case 'i': | |
169 if (flag) | |
170 xprintf("%d%d", TT.toystatfs->f_fsid.__val[0], TT.toystatfs->f_fsid.__val[1]); | |
171 else xprintf("%llu", TT.toystat->st_ino); | |
172 break; | |
173 case 'l': | |
174 if (flag) xprintf("%ld", TT.toystatfs->f_namelen); | |
175 break; | |
176 case 'n': | |
177 xprintf("%s", *toys.optargs); | |
178 break; | |
179 case 'N': | |
180 xprintf("`%s'", *toys.optargs); | |
181 break; | |
182 case 'o': | |
183 xprintf("%lu", TT.toystat->st_blksize); | |
184 break; | |
185 case 's': | |
186 if (flag) xprintf("%d", TT.toystatfs->f_frsize); | |
187 else xprintf("%llu", TT.toystat->st_size); | |
188 break; | |
189 case 'S': | |
190 if (flag) xprintf("%d", TT.toystatfs->f_bsize); | |
191 break; | |
192 case 't': | |
193 if (flag) xprintf("%lx", TT.toystatfs->f_type); | |
194 break; | |
195 case 'T': | |
196 if (flag) xprintf("Needs to be implemented"); | |
197 break; | |
198 case 'u': | |
199 xprintf("%lu", TT.toystat->st_uid); | |
200 break; | |
201 case 'U': | |
202 xprintf("%8s", TT.user_name->pw_name); | |
203 break; | |
204 case 'x': | |
205 xprintf("%s", date_stat_format(TT.toystat->st_atime)); | |
206 break; | |
207 case 'X': | |
208 xprintf("%llu", TT.toystat->st_atime); | |
209 break; | |
210 case 'y': | |
211 xprintf("%s", date_stat_format(TT.toystat->st_mtime)); | |
212 break; | |
213 case 'Y': | |
214 xprintf("%llu", TT.toystat->st_mtime); | |
215 break; | |
216 case 'z': | |
217 xprintf("%s", date_stat_format(TT.toystat->st_ctime)); | |
218 break; | |
219 case 'Z': | |
220 xprintf("%llu", TT.toystat->st_ctime); | |
221 default: | |
222 xprintf("%c", *format); | |
223 break; | |
255 } | 224 } |
256 } | 225 } |
257 // function to check the type/mode of file | 226 xprintf("\n"); |
258 if (!stat_flag_f) { | 227 } |
228 | |
229 void stat_main(void) | |
230 { | |
231 int flag_f = toys.optflags & FLAG_f, flag_c = toys.optflags & FLAG_c; | |
232 char *fmts[] = { | |
233 " File: %N\n" | |
234 " Size: %s\t Blocks: %S\t IO Blocks: %B\t%F\n" | |
235 "Device: %D\t Inode: %i\t Links: %h\n" | |
236 "Access: (%a/%A)\tUid: (%u/%U)\tGid: (%g/%G)\n" | |
237 "Access: %x\nModify: %y\nChange: %z", | |
238 | |
239 " File: \"%n\"\n" | |
240 " ID: %i Namelen: %l Type: %t\n" | |
241 "Block Size: %s Fundamental block size: %S\n" | |
242 "Blocks: Total: %b\tFree: %f\tAvailable: %a\n" | |
243 "Inodes: Total: %c\tFree: %d", | |
244 TT.fmt}; | |
245 | |
246 if (toys.optflags & FLAG_Z) error_exit("SELinux feature has not been implemented so far.."); | |
247 if (!flag_f) { | |
248 do_stat(*toys.optargs); | |
249 // function to check the type/mode of file | |
259 TT.file_type = check_type_file(TT.toystat->st_mode, TT.toystat->st_size); | 250 TT.file_type = check_type_file(TT.toystat->st_mode, TT.toystat->st_size); |
260 // check user and group name | 251 // check user and group name |
261 TT.user_name = getpwuid(TT.toystat->st_uid); | 252 TT.user_name = getpwuid(TT.toystat->st_uid); |
262 TT.group_name = getgrgid(TT.toystat->st_gid); | 253 TT.group_name = getgrgid(TT.toystat->st_gid); |
263 // function to get access in human readable format | 254 // function to get access in human readable format |
264 TT.access_str = get_access_str((TT.toystat->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)), TT.toystat->st_mode); | 255 TT.access_str = get_access_str(TT.toystat->st_mode & ~S_IFMT, TT.toystat->st_mode); |
265 TT.time_toy = gmtime(&(TT.toystat->st_atime)); | 256 } else do_statfs(*toys.optargs); |
266 } | 257 print_stat_format(fmts[!flag_c*flag_f+flag_c], flag_f); |
267 if (!(stat_flag_f |stat_flag_Z)) { | 258 } |
268 if (stat_format) print_stat_format(toys.optargs[0], stat_flag_f); | |
269 xprintf(" File: `%s'\n", toys.optargs[TT.toy_obj_file_arg]); | |
270 xprintf(" Size: %llu\t Blocks: %llu\t IO Blocks: %lu\t", TT.toystat->st_size, TT.toystat->st_blocks, TT.toystat->st_blksize); | |
271 xprintf("%s\n", TT.file_type); | |
272 xprintf("Device: %llxh\t Inode: %llu\t Links: %lu\n", TT.toystat->st_dev, TT.toystat->st_ino, TT.toystat->st_nlink); | |
273 xprintf("Access: (%04lo/%s)\tUid: (%lu/%8s)\tGid: (%lu/%8s)\n", (TT.toystat->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)), TT.access_str, TT.toystat->st_uid, TT.user_name->pw_name, TT.toystat->st_gid, TT.group_name->gr_name); | |
274 xprintf("Access: %s\nModify: %s\nChange: %s\n", date_stat_format(TT.toystat->st_atime), date_stat_format(TT.toystat->st_mtime), date_stat_format(TT.toystat->st_ctime)); | |
275 } else if (stat_flag_f) { | |
276 // implementation of statfs -f, file system | |
277 if (stat_format) print_stat_format(toys.optargs[0], stat_flag_f); | |
278 xprintf(" File: \"%s\"\n", toys.optargs[TT.toy_obj_file_arg]); | |
279 xprintf(" ID: %d%d Namelen: %ld Type: %lx\n", TT.toystatfs->f_fsid.__val[0], TT.toystatfs->f_fsid.__val[1], TT.toystatfs->f_namelen, TT.toystatfs->f_type); | |
280 xprintf("Block Size: %d Fundamental block size: %d\n", TT.toystatfs->f_bsize, TT.toystatfs->f_frsize); | |
281 xprintf("Blocks: Total: %lu\t", TT.toystatfs->f_blocks); | |
282 xprintf("Free: %lu\t", TT.toystatfs->f_bfree); | |
283 xprintf("Available: %lu\n", TT.toystatfs->f_bavail); | |
284 xprintf("Inodes: Total: %lu\t", TT.toystatfs->f_files); | |
285 xprintf("\tFree: %d\n", TT.toystatfs->f_ffree); | |
286 } | |
287 } |