Mercurial > hg > toybox
comparison toys/pending/stat.c @ 911:accabaaac666
stat: Separate stat and statfs
author | Felix Janda <felix.janda@posteo.de> |
---|---|
date | Sun, 26 May 2013 09:48:13 +0200 |
parents | 1b77a81859f6 |
children | f4f5132d5ac7 |
comparison
equal
deleted
inserted
replaced
910:1b77a81859f6 | 911:accabaaac666 |
---|---|
48 %c Total number of inodes | 48 %c Total number of inodes |
49 %d Number of free inodes | 49 %d Number of free inodes |
50 %f Number of free blocks | 50 %f Number of free blocks |
51 %i File system ID | 51 %i File system ID |
52 %l Maximum length of file names | 52 %l Maximum length of file names |
53 %n File name | |
53 %s Fragment size | 54 %s Fragment size |
54 %S Optimal transfer block size | 55 %S Optimal transfer block size |
55 %t File system type | 56 %t File system type |
56 */ | 57 */ |
57 | 58 |
58 #define FOR_stat | 59 #define FOR_stat |
59 #include "toys.h" | 60 #include "toys.h" |
60 | 61 |
61 GLOBALS( | 62 GLOBALS( |
62 char *fmt; | 63 char *fmt; |
63 char access_str[11]; | 64 void *stat; |
64 char *file_type; | 65 char *file_type; |
65 struct passwd *user_name; | 66 struct passwd *user_name; |
66 struct group *group_name; | 67 struct group *group_name; |
67 struct stat *stat; | 68 char access_str[11]; |
68 struct statfs *statfs; | |
69 ) | 69 ) |
70 | 70 |
71 | 71 |
72 static char * date_stat_format(time_t time) | 72 static char * date_stat_format(time_t time) |
73 { | 73 { |
75 | 75 |
76 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)); |
77 return buf; | 77 return buf; |
78 } | 78 } |
79 | 79 |
80 static void print_stat_format(char *format, int flag) | 80 static int print_stat(char type) { |
81 { | 81 struct stat *stat = (struct stat*)TT.stat; |
82 for (; *format; format++) { | 82 switch (type) { |
83 if (*format != '%') { | 83 case 'a': |
84 xprintf("%c", *format); | 84 xprintf("%04lo", stat->st_mode & ~S_IFMT); |
85 continue; | 85 break; |
86 } | 86 case 'A': |
87 format++; | 87 xprintf("%s", TT.access_str); |
88 switch (*format) { | 88 break; |
89 case 'a': | 89 case 'b': |
90 if (flag) xprintf("%lu", TT.statfs->f_bavail); | 90 xprintf("%llu", stat->st_blocks); |
91 else xprintf("%04lo",TT.stat->st_mode & ~S_IFMT); | 91 break; |
92 break; | 92 case 'B': |
93 case 'A': | 93 xprintf("%lu", stat->st_blksize); |
94 xprintf("%s",TT.access_str); | 94 break; |
95 break; | 95 case 'd': |
96 case 'b': | 96 xprintf("%ldd", stat->st_dev); |
97 if (flag) xprintf("%lu", TT.statfs->f_blocks); | 97 break; |
98 else xprintf("%llu", TT.stat->st_blocks); | 98 case 'D': |
99 break; | 99 xprintf("%llxh", stat->st_dev); |
100 case 'B': | 100 break; |
101 xprintf("%lu", TT.stat->st_blksize); | 101 case 'f': |
102 break; | 102 xprintf("%lx", stat->st_mode); |
103 case 'c': | 103 break; |
104 if (flag) xprintf("%lu", TT.statfs->f_files); | 104 case 'F': |
105 break; | 105 xprintf("%s", TT.file_type); |
106 case 'd': | 106 break; |
107 if (flag) xprintf("%lu", TT.statfs->f_ffree); | 107 case 'g': |
108 else xprintf("%ldd", TT.stat->st_dev); | 108 xprintf("%lu", stat->st_gid); |
109 break; | 109 break; |
110 case 'D': | 110 case 'G': |
111 xprintf("%llxh", TT.stat->st_dev); | 111 xprintf("%8s", TT.user_name->pw_name); |
112 break; | 112 break; |
113 case 'f': | 113 case 'h': |
114 if (flag) xprintf("%lu", TT.statfs->f_bfree); | 114 xprintf("%lu", stat->st_nlink); |
115 else xprintf("%lx", TT.stat->st_mode); | 115 break; |
116 break; | 116 case 'i': |
117 case 'F': | 117 xprintf("%llu", stat->st_ino); |
118 xprintf("%s", TT.file_type); | 118 break; |
119 break; | 119 case 'N': |
120 case 'g': | 120 xprintf("`%s'", *toys.optargs); |
121 xprintf("%lu", TT.stat->st_gid); | 121 break; |
122 break; | 122 case 'o': |
123 case 'G': | 123 xprintf("%lu", stat->st_blksize); |
124 xprintf("%8s", TT.user_name->pw_name); | 124 break; |
125 break; | 125 case 's': |
126 case 'h': | 126 xprintf("%llu", stat->st_size); |
127 xprintf("%lu", TT.stat->st_nlink); | 127 break; |
128 break; | 128 case 'u': |
129 case 'i': | 129 xprintf("%lu", stat->st_uid); |
130 if (flag) | 130 break; |
131 xprintf("%x%x", TT.statfs->f_fsid.__val[0], TT.statfs->f_fsid.__val[1]); | 131 case 'U': |
132 else xprintf("%llu", TT.stat->st_ino); | 132 xprintf("%8s", TT.user_name->pw_name); |
133 break; | 133 break; |
134 case 'l': | 134 case 'x': |
135 if (flag) xprintf("%ld", TT.statfs->f_namelen); | 135 xprintf("%s", date_stat_format(stat->st_atime)); |
136 break; | 136 break; |
137 case 'n': | 137 case 'X': |
138 xprintf("%s", *toys.optargs); | 138 xprintf("%llu", stat->st_atime); |
139 break; | 139 break; |
140 case 'N': | 140 case 'y': |
141 xprintf("`%s'", *toys.optargs); | 141 xprintf("%s", date_stat_format(stat->st_mtime)); |
142 break; | 142 break; |
143 case 'o': | 143 case 'Y': |
144 xprintf("%lu", TT.stat->st_blksize); | 144 xprintf("%llu", stat->st_mtime); |
145 break; | 145 break; |
146 case 's': | 146 case 'z': |
147 if (flag) xprintf("%d", TT.statfs->f_frsize); | 147 xprintf("%s", date_stat_format(stat->st_ctime)); |
148 else xprintf("%llu", TT.stat->st_size); | 148 break; |
149 break; | 149 case 'Z': |
150 case 'S': | 150 xprintf("%llu", stat->st_ctime); |
151 if (flag) xprintf("%d", TT.statfs->f_bsize); | 151 break; |
152 break; | 152 default: |
153 case 't': | 153 return 1; |
154 if (flag) xprintf("%lx", TT.statfs->f_type); | |
155 break; | |
156 case 'u': | |
157 xprintf("%lu", TT.stat->st_uid); | |
158 break; | |
159 case 'U': | |
160 xprintf("%8s", TT.user_name->pw_name); | |
161 break; | |
162 case 'x': | |
163 xprintf("%s", date_stat_format(TT.stat->st_atime)); | |
164 break; | |
165 case 'X': | |
166 xprintf("%llu", TT.stat->st_atime); | |
167 break; | |
168 case 'y': | |
169 xprintf("%s", date_stat_format(TT.stat->st_mtime)); | |
170 break; | |
171 case 'Y': | |
172 xprintf("%llu", TT.stat->st_mtime); | |
173 break; | |
174 case 'z': | |
175 xprintf("%s", date_stat_format(TT.stat->st_ctime)); | |
176 break; | |
177 case 'Z': | |
178 xprintf("%llu", TT.stat->st_ctime); | |
179 default: | |
180 xprintf("%c", *format); | |
181 break; | |
182 } | |
183 } | 154 } |
184 xprintf("\n"); | 155 return 0; |
185 } | 156 } |
186 | 157 |
187 int do_stat(char *path) | 158 static int print_statfs(char type) { |
188 { | 159 struct statfs *statfs = (struct statfs*)TT.stat; |
160 switch (type) { | |
161 case 'a': | |
162 xprintf("%lu", statfs->f_bavail); | |
163 break; | |
164 case 'b': | |
165 xprintf("%lu", statfs->f_blocks); | |
166 break; | |
167 case 'c': | |
168 xprintf("%lu", statfs->f_files); | |
169 break; | |
170 case 'd': | |
171 xprintf("%lu", statfs->f_ffree); | |
172 break; | |
173 case 'f': | |
174 xprintf("%lu", statfs->f_bfree); | |
175 break; | |
176 case 'i': | |
177 xprintf("%x%x", statfs->f_fsid.__val[0], statfs->f_fsid.__val[1]); | |
178 break; | |
179 case 'l': | |
180 xprintf("%ld", statfs->f_namelen); | |
181 break; | |
182 case 's': | |
183 xprintf("%d", statfs->f_frsize); | |
184 break; | |
185 case 'S': | |
186 xprintf("%d", statfs->f_bsize); | |
187 break; | |
188 case 't': | |
189 xprintf("%lx", statfs->f_type); | |
190 break; | |
191 default: | |
192 return 1; | |
193 } | |
194 return 0; | |
195 } | |
196 | |
197 static int do_stat(char *path) | |
198 { | |
199 struct stat *statf = (struct stat*)TT.stat; | |
189 size_t i; | 200 size_t i; |
190 struct { | 201 struct { |
191 mode_t mode; | 202 mode_t mode; |
192 char *str; | 203 char *str; |
193 } types[] = { | 204 } types[] = { |
198 {S_IFIFO, "FIFO (named pipe)"}, | 209 {S_IFIFO, "FIFO (named pipe)"}, |
199 {S_IFLNK, "symbolic link"}, | 210 {S_IFLNK, "symbolic link"}, |
200 {S_IFSOCK, "socket"} | 211 {S_IFSOCK, "socket"} |
201 }; | 212 }; |
202 | 213 |
203 if (stat(path, TT.stat) < 0) return 1; | 214 if (stat(path, statf) < 0) return 1; |
204 | 215 |
205 for (i = 0; i < sizeof(types)/sizeof(*types); i++) | 216 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; | 217 if ((statf->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) | 218 if (!statf->st_size && (statf->st_mode & S_IFMT) == S_IFREG) |
208 TT.file_type = "regular empty file"; | 219 TT.file_type = "regular empty file"; |
209 | 220 |
210 // check user and group name | 221 // check user and group name |
211 TT.user_name = getpwuid(TT.stat->st_uid); | 222 TT.user_name = getpwuid(statf->st_uid); |
212 TT.group_name = getgrgid(TT.stat->st_gid); | 223 TT.group_name = getgrgid(statf->st_gid); |
213 // function to get access in human readable format | 224 // function to get access in human readable format |
214 format_mode(&TT.access_str, TT.stat->st_mode); | 225 format_mode(&TT.access_str, statf->st_mode); |
215 return 0; | 226 return 0; |
216 } | 227 } |
217 | 228 |
218 int do_statfs(char *path) | 229 static int do_statfs(char *path) |
219 { | 230 { |
220 return statfs(path, TT.statfs) < 0; | 231 return statfs(path, TT.stat) < 0; |
221 } | 232 } |
222 | 233 |
223 void stat_main(void) | 234 void stat_main(void) |
224 { | 235 { |
225 int flag_f = toys.optflags & FLAG_f; | 236 struct { |
226 char *fmt; | 237 char *fmt; |
227 int (*do_it)(char*); | 238 int (*do_it)(char*); |
228 | 239 int (*print_it)(char); |
229 if (!flag_f) { | 240 size_t size; |
230 TT.stat = xmalloc(sizeof(struct stat)); | 241 } d, ds[2] = { |
231 fmt = " File: %N\n" | 242 {" File: %N\n" |
232 " Size: %s\t Blocks: %b\t IO Blocks: %B\t%F\n" | 243 " Size: %s\t Blocks: %b\t IO Blocks: %B\t%F\n" |
233 "Device: %D\t Inode: %i\t Links: %h\n" | 244 "Device: %D\t Inode: %i\t Links: %h\n" |
234 "Access: (%a/%A)\tUid: (%u/%U)\tGid: (%g/%G)\n" | 245 "Access: (%a/%A)\tUid: (%u/%U)\tGid: (%g/%G)\n" |
235 "Access: %x\nModify: %y\nChange: %z"; | 246 "Access: %x\nModify: %y\nChange: %z", |
236 do_it = do_stat; | 247 do_stat, print_stat, sizeof(struct stat)}, |
237 } else { | 248 {" File: \"%n\"\n" |
238 TT.statfs = xmalloc(sizeof(struct statfs)); | 249 " ID: %i Namelen: %l Type: %t\n" |
239 fmt = " File: \"%n\"\n" | 250 "Block Size: %s Fundamental block size: %S\n" |
240 " ID: %i Namelen: %l Type: %t\n" | 251 "Blocks: Total: %b\tFree: %f\tAvailable: %a\n" |
241 "Block Size: %s Fundamental block size: %S\n" | 252 "Inodes: Total: %c\tFree: %d", |
242 "Blocks: Total: %b\tFree: %f\tAvailable: %a\n" | 253 do_statfs, print_statfs, sizeof(struct statfs)} |
243 "Inodes: Total: %c\tFree: %d"; | 254 }; |
244 do_it = do_statfs; | 255 |
245 } | 256 d = ds[toys.optflags & FLAG_f]; |
246 if (toys.optflags & FLAG_c) fmt = TT.fmt; | 257 TT.stat = xmalloc(d.size); |
258 if (toys.optflags & FLAG_c) d.fmt = TT.fmt; | |
247 | 259 |
248 for (; *toys.optargs; toys.optargs++) { | 260 for (; *toys.optargs; toys.optargs++) { |
249 if (do_it(*toys.optargs)) { | 261 char *format = d.fmt; |
262 if (d.do_it(*toys.optargs)) { | |
250 perror_msg("'%s'", *toys.optargs); | 263 perror_msg("'%s'", *toys.optargs); |
251 continue; | 264 continue; |
252 } | 265 } |
253 print_stat_format(fmt, flag_f); | 266 for (; *format; format++) { |
267 if (*format != '%') { | |
268 xputc(*format); | |
269 continue; | |
270 } | |
271 format++; | |
272 if (*format == 'n') xprintf("%s", *toys.optargs); | |
273 else if (d.print_it(*format)) xputc(*format); | |
274 } | |
275 xputc('\n'); | |
254 } | 276 } |
255 } | 277 |
278 if(CFG_TOYBOX_FREE) free(TT.stat); | |
279 } |