Mercurial > hg > toybox
comparison toys/pending/stat.c @ 910:1b77a81859f6
stat: Add support for stat'ing multiple files
author | Felix Janda <felix.janda@posteo.de> |
---|---|
date | Sat, 25 May 2013 21:58:14 +0200 |
parents | 6bb5c8ace240 |
children | accabaaac666 |
comparison
equal
deleted
inserted
replaced
909:9a732a0f8ddc | 910:1b77a81859f6 |
---|---|
67 struct stat *stat; | 67 struct stat *stat; |
68 struct statfs *statfs; | 68 struct statfs *statfs; |
69 ) | 69 ) |
70 | 70 |
71 | 71 |
72 static char * check_type_file(mode_t mode, size_t size) | |
73 { | |
74 if (S_ISREG(mode)) { | |
75 if (size) return "regular file"; | |
76 return "regular empty file"; | |
77 } | |
78 if (S_ISDIR(mode)) return "directory"; | |
79 if (S_ISCHR(mode)) return "character device"; | |
80 if (S_ISBLK(mode)) return "block device"; | |
81 if (S_ISFIFO(mode)) return "FIFO (named pipe)"; | |
82 if (S_ISLNK(mode)) return "symbolic link"; | |
83 if (S_ISSOCK(mode)) return "socket"; | |
84 } | |
85 | |
86 static char * date_stat_format(time_t time) | 72 static char * date_stat_format(time_t time) |
87 { | 73 { |
88 static char buf[36]; | 74 static char buf[36]; |
89 | 75 |
90 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S.000000000", localtime(&time)); | 76 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S.000000000", localtime(&time)); |
140 case 'h': | 126 case 'h': |
141 xprintf("%lu", TT.stat->st_nlink); | 127 xprintf("%lu", TT.stat->st_nlink); |
142 break; | 128 break; |
143 case 'i': | 129 case 'i': |
144 if (flag) | 130 if (flag) |
145 xprintf("%d%d", TT.statfs->f_fsid.__val[0], TT.statfs->f_fsid.__val[1]); | 131 xprintf("%x%x", TT.statfs->f_fsid.__val[0], TT.statfs->f_fsid.__val[1]); |
146 else xprintf("%llu", TT.stat->st_ino); | 132 else xprintf("%llu", TT.stat->st_ino); |
147 break; | 133 break; |
148 case 'l': | 134 case 'l': |
149 if (flag) xprintf("%ld", TT.statfs->f_namelen); | 135 if (flag) xprintf("%ld", TT.statfs->f_namelen); |
150 break; | 136 break; |
196 } | 182 } |
197 } | 183 } |
198 xprintf("\n"); | 184 xprintf("\n"); |
199 } | 185 } |
200 | 186 |
187 int do_stat(char *path) | |
188 { | |
189 size_t i; | |
190 struct { | |
191 mode_t mode; | |
192 char *str; | |
193 } types[] = { | |
194 {S_IFDIR, "directory"}, | |
195 {S_IFCHR, "character device"}, | |
196 {S_IFBLK, "block device"}, | |
197 {S_IFREG, "regular file"}, | |
198 {S_IFIFO, "FIFO (named pipe)"}, | |
199 {S_IFLNK, "symbolic link"}, | |
200 {S_IFSOCK, "socket"} | |
201 }; | |
202 | |
203 if (stat(path, TT.stat) < 0) return 1; | |
204 | |
205 for (i = 0; i < sizeof(types)/sizeof(*types); i++) | |
206 if((TT.stat->st_mode&S_IFMT) == types[i].mode) TT.file_type = types[i].str; | |
207 if(!TT.stat->st_size && (TT.stat->st_mode & S_IFMT) == S_IFREG) | |
208 TT.file_type = "regular empty file"; | |
209 | |
210 // check user and group name | |
211 TT.user_name = getpwuid(TT.stat->st_uid); | |
212 TT.group_name = getgrgid(TT.stat->st_gid); | |
213 // function to get access in human readable format | |
214 format_mode(&TT.access_str, TT.stat->st_mode); | |
215 return 0; | |
216 } | |
217 | |
218 int do_statfs(char *path) | |
219 { | |
220 return statfs(path, TT.statfs) < 0; | |
221 } | |
222 | |
201 void stat_main(void) | 223 void stat_main(void) |
202 { | 224 { |
203 int flag_f = toys.optflags & FLAG_f, flag_c = toys.optflags & FLAG_c; | 225 int flag_f = toys.optflags & FLAG_f; |
204 char *fmts[] = { | 226 char *fmt; |
205 " File: %N\n" | 227 int (*do_it)(char*); |
206 " Size: %s\t Blocks: %S\t IO Blocks: %B\t%F\n" | |
207 "Device: %D\t Inode: %i\t Links: %h\n" | |
208 "Access: (%a/%A)\tUid: (%u/%U)\tGid: (%g/%G)\n" | |
209 "Access: %x\nModify: %y\nChange: %z", | |
210 | |
211 " File: \"%n\"\n" | |
212 " ID: %i Namelen: %l Type: %t\n" | |
213 "Block Size: %s Fundamental block size: %S\n" | |
214 "Blocks: Total: %b\tFree: %f\tAvailable: %a\n" | |
215 "Inodes: Total: %c\tFree: %d", | |
216 TT.fmt}; | |
217 | 228 |
218 if (!flag_f) { | 229 if (!flag_f) { |
219 TT.stat = xmalloc(sizeof(struct stat)); | 230 TT.stat = xmalloc(sizeof(struct stat)); |
220 if (stat(*toys.optargs, TT.stat) < 0) | 231 fmt = " File: %N\n" |
221 perror_exit("stat: '%s'", *toys.optargs); | 232 " Size: %s\t Blocks: %b\t IO Blocks: %B\t%F\n" |
222 // function to check the type/mode of file | 233 "Device: %D\t Inode: %i\t Links: %h\n" |
223 TT.file_type = check_type_file(TT.stat->st_mode, TT.stat->st_size); | 234 "Access: (%a/%A)\tUid: (%u/%U)\tGid: (%g/%G)\n" |
224 // check user and group name | 235 "Access: %x\nModify: %y\nChange: %z"; |
225 TT.user_name = getpwuid(TT.stat->st_uid); | 236 do_it = do_stat; |
226 TT.group_name = getgrgid(TT.stat->st_gid); | |
227 // function to get access in human readable format | |
228 format_mode(&TT.access_str, TT.stat->st_mode); | |
229 } else { | 237 } else { |
230 TT.statfs = xmalloc(sizeof(struct statfs)); | 238 TT.statfs = xmalloc(sizeof(struct statfs)); |
231 if (statfs(*toys.optargs, TT.statfs) < 0) | 239 fmt = " File: \"%n\"\n" |
232 perror_exit("statfs: '%s'", *toys.optargs); | 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 do_it = do_statfs; | |
233 } | 245 } |
234 print_stat_format(fmts[!flag_c*flag_f+flag_c], flag_f); | 246 if (toys.optflags & FLAG_c) fmt = TT.fmt; |
235 } | 247 |
248 for (; *toys.optargs; toys.optargs++) { | |
249 if (do_it(*toys.optargs)) { | |
250 perror_msg("'%s'", *toys.optargs); | |
251 continue; | |
252 } | |
253 print_stat_format(fmt, flag_f); | |
254 } | |
255 } |