Mercurial > hg > toybox
comparison toys/pending/stat.c @ 914:91d15ead5602
Stat cleanup.
Put global stat info in a union so we don't have to malloc it and thus don't need an explicit size tracked in main(). Make date_stat_format() take a timespec and take advantage of stat having an embedded timespec (nanosecond printing), typecast the long long prints for XYZ because on some 32 bit platforms it's an int.
author | Rob Landley <rob@landley.net> |
---|---|
date | Sat, 01 Jun 2013 20:47:16 -0500 |
parents | f4f5132d5ac7 |
children | b92cb3cc9696 |
comparison
equal
deleted
inserted
replaced
913:7fed25030389 | 914:91d15ead5602 |
---|---|
36 #include "toys.h" | 36 #include "toys.h" |
37 | 37 |
38 GLOBALS( | 38 GLOBALS( |
39 char *fmt; | 39 char *fmt; |
40 | 40 |
41 void *stat; | 41 union { |
42 struct stat st; | |
43 struct statfs sf; | |
44 } stat; | |
42 struct passwd *user_name; | 45 struct passwd *user_name; |
43 struct group *group_name; | 46 struct group *group_name; |
44 char *ftname, access_str[11]; | 47 char *ftname, access_str[11]; |
45 ) | 48 ) |
46 | 49 |
47 | 50 |
48 static void date_stat_format(time_t time, int nano) | 51 // Note: the atime, mtime, and ctime fields in struct stat are the start |
49 { | 52 // of embedded struct timespec, but posix won't let them use that |
50 static char buf[36]; | 53 // struct definition for legacy/namespace reasons. |
51 int len; | 54 |
52 | 55 static void date_stat_format(struct timespec *ts) |
53 len = strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S.", localtime(&time)); | 56 { |
54 sprintf(buf+len, "%09d", nano); | 57 strftime(toybuf, sizeof(toybuf), "%Y-%m-%d %H:%M:%S", |
55 xprintf("%s", buf); | 58 localtime(&(ts->tv_sec))); |
59 xprintf("%s.%09d", toybuf, ts->tv_nsec); | |
56 } | 60 } |
57 | 61 |
58 static int print_stat(char type) | 62 static int print_stat(char type) |
59 { | 63 { |
60 struct stat *stat = (struct stat*)TT.stat; | 64 struct stat *stat = (struct stat *)&TT.stat; |
61 | 65 |
62 switch (type) { | 66 switch (type) { |
63 case 'a': | 67 case 'a': |
64 xprintf("%04lo", stat->st_mode & ~S_IFMT); | 68 xprintf("%04lo", stat->st_mode & ~S_IFMT); |
65 break; | 69 break; |
66 case 'A': | 70 case 'A': |
67 xprintf("%s", TT.access_str); | 71 xprintf("%s", TT.access_str); |
68 break; | 72 break; |
73 | |
69 case 'b': | 74 case 'b': |
70 xprintf("%llu", stat->st_blocks); | 75 xprintf("%llu", stat->st_blocks); |
71 break; | 76 break; |
77 | |
72 case 'B': | 78 case 'B': |
73 xprintf("%lu", stat->st_blksize); | 79 xprintf("%lu", stat->st_blksize); |
74 break; | 80 break; |
75 case 'd': | 81 case 'd': |
76 xprintf("%ldd", stat->st_dev); | 82 xprintf("%ldd", stat->st_dev); |
109 xprintf("%lu", stat->st_uid); | 115 xprintf("%lu", stat->st_uid); |
110 break; | 116 break; |
111 case 'U': | 117 case 'U': |
112 xprintf("%8s", TT.user_name->pw_name); | 118 xprintf("%8s", TT.user_name->pw_name); |
113 break; | 119 break; |
120 | |
114 case 'x': | 121 case 'x': |
115 date_stat_format(stat->st_atime, stat->st_atim.tv_nsec); | 122 date_stat_format((void *)&stat->st_atime); |
116 break; | 123 break; |
117 case 'X': | 124 case 'X': |
118 xprintf("%llu", stat->st_atime); | 125 xprintf("%llu", (long long)stat->st_atime); |
119 break; | 126 break; |
120 case 'y': | 127 case 'y': |
121 date_stat_format(stat->st_mtime, stat->st_mtim.tv_nsec); | 128 date_stat_format((void *)&stat->st_mtime); |
122 break; | 129 break; |
123 case 'Y': | 130 case 'Y': |
124 xprintf("%llu", stat->st_mtime); | 131 xprintf("%llu", (long long)stat->st_mtime); |
125 break; | 132 break; |
126 case 'z': | 133 case 'z': |
127 date_stat_format(stat->st_ctime, stat->st_ctim.tv_nsec); | 134 date_stat_format((void *)&stat->st_ctime); |
128 break; | 135 break; |
129 case 'Z': | 136 case 'Z': |
130 xprintf("%llu", stat->st_ctime); | 137 xprintf("%llu", (long long)stat->st_ctime); |
131 break; | 138 break; |
139 | |
132 default: | 140 default: |
133 return 1; | 141 return 1; |
134 } | 142 } |
135 return 0; | 143 return 0; |
136 } | 144 } |
137 | 145 |
138 static int print_statfs(char type) { | 146 static int print_statfs(char type) { |
139 struct statfs *statfs = (struct statfs*)TT.stat; | 147 struct statfs *statfs = (struct statfs *)&TT.stat; |
140 | 148 |
141 switch (type) { | 149 switch (type) { |
142 case 'a': | 150 case 'a': |
143 xprintf("%lu", statfs->f_bavail); | 151 xprintf("%lu", statfs->f_bavail); |
144 break; | 152 break; |
175 return 0; | 183 return 0; |
176 } | 184 } |
177 | 185 |
178 static int do_stat(char *path) | 186 static int do_stat(char *path) |
179 { | 187 { |
180 struct stat *statf = (struct stat*)TT.stat; | 188 struct stat *statf = (struct stat*)&TT.stat; |
181 char *types = "character device\0directory\0block device\0" \ | 189 char *types = "character device\0directory\0block device\0" \ |
182 "regular file\0symbolic link\0socket\0FIFO (named pipe)"; | 190 "regular file\0symbolic link\0socket\0FIFO (named pipe)"; |
183 int i, filetype; | 191 int i, filetype; |
184 | 192 |
185 if (stat(path, statf) < 0) return 1; | 193 if (stat(path, statf) < 0) return 1; |
200 return 0; | 208 return 0; |
201 } | 209 } |
202 | 210 |
203 static int do_statfs(char *path) | 211 static int do_statfs(char *path) |
204 { | 212 { |
205 return statfs(path, TT.stat) < 0; | 213 return statfs(path, (void *)&TT.stat) < 0; |
206 } | 214 } |
207 | 215 |
208 void stat_main(void) | 216 void stat_main(void) |
209 { | 217 { |
210 struct { | 218 struct { |
211 char *fmt; | 219 char *fmt; |
212 int (*do_it)(char*); | 220 int (*do_it)(char*); |
213 int (*print_it)(char); | 221 int (*print_it)(char); |
214 size_t size; | |
215 } d, ds[2] = { | 222 } d, ds[2] = { |
216 {" File: %N\n" | 223 {" File: %N\n" |
217 " Size: %s\t Blocks: %b\t IO Blocks: %B\t%F\n" | 224 " Size: %s\t Blocks: %b\t IO Blocks: %B\t%F\n" |
218 "Device: %D\t Inode: %i\t Links: %h\n" | 225 "Device: %D\t Inode: %i\t Links: %h\n" |
219 "Access: (%a/%A)\tUid: (%u/%U)\tGid: (%g/%G)\n" | 226 "Access: (%a/%A)\tUid: (%u/%U)\tGid: (%g/%G)\n" |
220 "Access: %x\nModify: %y\nChange: %z", | 227 "Access: %x\nModify: %y\nChange: %z", |
221 do_stat, print_stat, sizeof(struct stat)}, | 228 do_stat, print_stat}, |
222 {" File: \"%n\"\n" | 229 {" File: \"%n\"\n" |
223 " ID: %i Namelen: %l Type: %t\n" | 230 " ID: %i Namelen: %l Type: %t\n" |
224 "Block Size: %s Fundamental block size: %S\n" | 231 "Block Size: %s Fundamental block size: %S\n" |
225 "Blocks: Total: %b\tFree: %f\tAvailable: %a\n" | 232 "Blocks: Total: %b\tFree: %f\tAvailable: %a\n" |
226 "Inodes: Total: %c\tFree: %d", | 233 "Inodes: Total: %c\tFree: %d", |
227 do_statfs, print_statfs, sizeof(struct statfs)} | 234 do_statfs, print_statfs} |
228 }; | 235 }; |
229 | 236 |
230 d = ds[toys.optflags & FLAG_f]; | 237 d = ds[toys.optflags & FLAG_f]; |
231 TT.stat = xmalloc(d.size); | |
232 if (toys.optflags & FLAG_c) d.fmt = TT.fmt; | 238 if (toys.optflags & FLAG_c) d.fmt = TT.fmt; |
233 | 239 |
234 for (; *toys.optargs; toys.optargs++) { | 240 for (; *toys.optargs; toys.optargs++) { |
235 char *format = d.fmt; | 241 char *format = d.fmt; |
236 if (d.do_it(*toys.optargs)) { | 242 if (d.do_it(*toys.optargs)) { |
246 if (*format == 'n') xprintf("%s", *toys.optargs); | 252 if (*format == 'n') xprintf("%s", *toys.optargs); |
247 else if (d.print_it(*format)) xputc(*format); | 253 else if (d.print_it(*format)) xputc(*format); |
248 } | 254 } |
249 xputc('\n'); | 255 xputc('\n'); |
250 } | 256 } |
251 | 257 } |
252 if(CFG_TOYBOX_FREE) free(TT.stat); | |
253 } |