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 }