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 }