Mercurial > hg > toybox
comparison toys/pending/stat.c @ 747:68d6c1ce7bba
Add stat submission to new "pending" directory, along with infrastructure to support pending.
author | Rob Landley <rob@landley.net> |
---|---|
date | Mon, 10 Dec 2012 21:08:42 -0600 |
parents | |
children | 874d2e646f2d |
comparison
equal
deleted
inserted
replaced
746:5caa4035c1c8 | 747:68d6c1ce7bba |
---|---|
1 /* vi: set sw=4 ts=4 | |
2 * | |
3 * stat.c : display file or file system status | |
4 * anand.sinha85@gmail.com | |
5 * Copyright 2012 <warior.linux@gmail.com> | |
6 * | |
7 * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/stat.html | |
8 USE_STAT(NEWTOY(stat, "LZfc", TOYFLAG_BIN)) | |
9 config STAT | |
10 bool st | |
11 default n | |
12 help | |
13 Usage: stat [OPTION] FILE... | |
14 display file or file system status | |
15 -Z, --context | |
16 print the security context information if available | |
17 -f, --file-system | |
18 display file system status instead of file status | |
19 -c --format=FORMAT | |
20 use the specified FORMAT instead of the default; output a newline after each use of FORMAT | |
21 --help display this help and exit | |
22 The valid format sequences for files (without --file-system): | |
23 %a Access rights in octal | |
24 %A Access rights in human readable form | |
25 %b Number of blocks allocated (see | |
26 %B The size in bytes of each block reported by | |
27 %d Device number in decimal | |
28 %D Device number in hex | |
29 %f Raw mode in hex | |
30 %F File type | |
31 %G Group name of owner | |
32 %h Number of hard links | |
33 %i Inode number | |
34 %n File name | |
35 %N Quoted file name with dereference if symbolic link | |
36 %o I/O block size | |
37 %s Total size, in bytes | |
38 %t Major device type in hex | |
39 %T Minor device type in hex | |
40 %u User ID of owner | |
41 %U User name of owner | |
42 %x Time of last access | |
43 %X Time of last access as seconds since Epoch | |
44 %y Time of last modification | |
45 %Y Time of last modification as seconds since Epoch | |
46 %z Time of last change | |
47 %Z Time of last change as seconds since Epoch | |
48 */ | |
49 | |
50 #define FOR_stat | |
51 #include "toys.h" | |
52 #define SIZE_DATE_TIME_STAT 36 | |
53 #define access_string(x, s, i) if((x&7) & 1) \ | |
54 s[9 - i * 3] = 'x'; \ | |
55 else \ | |
56 s[9 - i * 3] = '-'; \ | |
57 if(((x&7) >> 1) & 1) \ | |
58 s[9 - (i * 3 + 1)] = 'w'; \ | |
59 else \ | |
60 s[9 - (i * 3 + 1)] = '-'; \ | |
61 if(((x&7) >> 2) & 1) \ | |
62 s[9 - (i * 3 + 2)] = 'r'; \ | |
63 else \ | |
64 s[9 - (i * 3 + 2)] = '-'; | |
65 | |
66 static char * check_type_file(mode_t, size_t); | |
67 static char * get_access_str(unsigned long, mode_t); | |
68 static char * date_stat_format(time_t ); | |
69 static int do_stat(const char *); | |
70 static int do_statfs(const char *); | |
71 inline void print_stat_format(char *, int); | |
72 | |
73 GLOBALS( | |
74 char * access_str; | |
75 char * file_type; | |
76 struct passwd * user_name; struct group * group_name; struct tm *time_toy; | |
77 struct stat * toystat; | |
78 struct statfs * toystatfs; | |
79 int toy_obj_file_arg; | |
80 ) | |
81 | |
82 | |
83 static int do_stat(const char * file_name){ | |
84 TT.toystat = (struct stat*)malloc(sizeof(struct stat)); | |
85 if(stat(file_name, TT.toystat) < 0){ | |
86 perror_msg("Error: unable to get information about the file, stat\n", file_name); | |
87 toys.exitval = EXIT_FAILURE; | |
88 } | |
89 return 0; | |
90 } | |
91 | |
92 static int do_statfs(const char * file_name){ | |
93 TT.toystatfs = (struct statfs *)malloc(sizeof(struct statfs)); | |
94 if(statfs(file_name, TT.toystatfs) < 0){ | |
95 perror_msg("Error: unable to get information about the file, statfs\n", file_name); | |
96 toys.exitval = EXIT_FAILURE; | |
97 } | |
98 return 0; | |
99 } | |
100 | |
101 static char * check_type_file(mode_t mode, size_t size){ | |
102 if(S_ISREG(mode)){ | |
103 if(size) | |
104 return "regular file"; | |
105 return "regular empty file"; | |
106 } | |
107 if(S_ISDIR(mode)) | |
108 return "directory"; | |
109 if(S_ISCHR(mode)) | |
110 return "character device"; | |
111 if(S_ISBLK(mode)) | |
112 return "block device"; | |
113 if(S_ISFIFO(mode)) | |
114 return "FIFO (named pipe)"; | |
115 if(S_ISLNK(mode)) | |
116 return "symbolic link"; | |
117 if(S_ISSOCK(mode)) | |
118 return "socket"; | |
119 } | |
120 | |
121 static char * get_access_str(unsigned long pernission, mode_t mode){ | |
122 static char access_string[10]; | |
123 int i; | |
124 if(S_ISDIR(mode)) | |
125 access_string[0] = 'd'; | |
126 else | |
127 access_string[0] = '-'; | |
128 for(i = 0; i < 3; i++){ | |
129 access_string(pernission >> (i * 3) & 7, access_string, i); | |
130 } | |
131 access_string[10] = '\0'; | |
132 return access_string; | |
133 } | |
134 | |
135 static char * date_stat_format(time_t time){ | |
136 static char buf[SIZE_DATE_TIME_STAT]; | |
137 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S.000000000", localtime(&time)); | |
138 return buf; | |
139 } | |
140 | |
141 inline void print_stat_format(char *format, int flag){ | |
142 format++; | |
143 switch(*format){ | |
144 case 'a': | |
145 if(flag) | |
146 xprintf("%lu\n", TT.toystatfs->f_bavail); | |
147 else | |
148 xprintf("%04lo\n",TT.toystat->st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)); | |
149 break; | |
150 case 'A': | |
151 xprintf("%s\n",TT.access_str); | |
152 break; | |
153 case 'b': | |
154 if(flag) | |
155 xprintf("%lu\n", TT.toystatfs->f_blocks); | |
156 else | |
157 xprintf("%llu\n", TT.toystat->st_blocks); | |
158 break; | |
159 case 'B': | |
160 xprintf("%lu\n", TT.toystat->st_blksize); | |
161 break; | |
162 case 'c': | |
163 if(flag) | |
164 xprintf("%lu\n", TT.toystatfs->f_files); | |
165 break; | |
166 case 'C': | |
167 xprintf("Currently feature is not supported\n"); | |
168 break; | |
169 case 'd': | |
170 if(flag) | |
171 xprintf("%lu\n", TT.toystatfs->f_ffree); | |
172 else | |
173 xprintf("%ldd\n", TT.toystat->st_dev); | |
174 break; | |
175 case 'D': | |
176 xprintf("%llxh\n", TT.toystat->st_dev); | |
177 break; | |
178 case 'f': | |
179 if(flag) | |
180 xprintf("%lu\n", TT.toystatfs->f_bfree); | |
181 else | |
182 xprintf("%lx\n", TT.toystat->st_mode); | |
183 break; | |
184 case 'F': | |
185 xprintf("%s\n", TT.file_type); | |
186 break; | |
187 case 'g': | |
188 xprintf("%lu\n", TT.toystat->st_uid); | |
189 break; | |
190 case 'G': | |
191 xprintf("%8s\n", TT.user_name->pw_name); | |
192 break; | |
193 case 'h': | |
194 xprintf("%lu\n", TT.toystat->st_nlink); | |
195 break; | |
196 case 'i': | |
197 if(flag) | |
198 xprintf("%d%d\n", TT.toystatfs->f_fsid.__val[0], TT.toystatfs->f_fsid.__val[1]); | |
199 else | |
200 xprintf("%llu\n", TT.toystat->st_ino); | |
201 break; | |
202 case 'l': | |
203 if(flag) | |
204 xprintf("need to implement\n"); | |
205 break; | |
206 case 'n': | |
207 xprintf("%s\n", toys.optargs[TT.toy_obj_file_arg]); | |
208 break; | |
209 case 'N': | |
210 xprintf("`%s\n'", toys.optargs[TT.toy_obj_file_arg]); | |
211 break; | |
212 case 'o': | |
213 xprintf("%lu\n", TT.toystat->st_blksize); | |
214 break; | |
215 case 's': | |
216 if(flag) | |
217 xprintf("%d\n", TT.toystatfs->f_frsize); | |
218 else | |
219 xprintf("%llu\n", TT.toystat->st_size); | |
220 break; | |
221 case 'S': | |
222 if(flag) | |
223 xprintf("%d\n", TT.toystatfs->f_bsize); | |
224 break; | |
225 case 't': | |
226 if(flag) | |
227 xprintf("%lx\n", TT.toystatfs->f_type); | |
228 break; | |
229 case 'T': | |
230 if(flag) | |
231 xprintf("Needs to be implemented\n"); | |
232 break; | |
233 case 'u': | |
234 xprintf("%lu\n", TT.toystat->st_uid); | |
235 break; | |
236 case 'U': | |
237 xprintf("%8s\n", TT.user_name->pw_name); | |
238 break; | |
239 case 'x': | |
240 xprintf("%s\n", date_stat_format(TT.toystat->st_atime)); | |
241 break; | |
242 case 'X': | |
243 xprintf("%llu\n", TT.toystat->st_atime); | |
244 break; | |
245 case 'y': | |
246 xprintf("%s\n", date_stat_format(TT.toystat->st_mtime)); | |
247 break; | |
248 case 'Y': | |
249 xprintf("%llu\n", TT.toystat->st_mtime); | |
250 break; | |
251 case 'z': | |
252 xprintf("%s\n", date_stat_format(TT.toystat->st_ctime)); | |
253 break; | |
254 case 'Z': | |
255 xprintf("%llu\n", TT.toystat->st_ctime); | |
256 default: | |
257 xprintf("%c\n", *format); | |
258 break; | |
259 } | |
260 exit(0); | |
261 } | |
262 | |
263 void stat_main(void){ | |
264 int stat_flag_Z = 0, stat_flag_f = 0, stat_flag_c = 0, stat_format = 0; | |
265 if(toys.optargs){ | |
266 if(toys.optflags & 1){ | |
267 stat_flag_c = 1; | |
268 TT.toy_obj_file_arg = 1; | |
269 stat_format = 1; | |
270 } | |
271 if(toys.optflags & (1 << 1)){ | |
272 stat_flag_f = 1; | |
273 if(do_statfs(toys.optargs[TT.toy_obj_file_arg]) != 0) | |
274 xprintf("Error STATFS\n"); | |
275 }else | |
276 if(do_stat(toys.optargs[TT.toy_obj_file_arg]) != 0) | |
277 xprintf("Error STAT\n"); | |
278 if(toys.optflags & (1 << 2)){ | |
279 stat_flag_Z = 1; | |
280 xprintf("SELinux feature has not been implemented so far..\n"); | |
281 } | |
282 } | |
283 // function to check the type/mode of file | |
284 if(!stat_flag_f){ | |
285 TT.file_type = check_type_file(TT.toystat->st_mode, TT.toystat->st_size); | |
286 // check user and group name | |
287 TT.user_name = getpwuid(TT.toystat->st_uid); | |
288 TT.group_name = getgrgid(TT.toystat->st_gid); | |
289 // function to get access in human readable format | |
290 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); | |
291 TT.time_toy = gmtime(&(TT.toystat->st_atime)); | |
292 } | |
293 if(!(stat_flag_f |stat_flag_Z)){ | |
294 if(stat_format) | |
295 print_stat_format(toys.optargs[0], stat_flag_f); | |
296 xprintf(" File: `%s'\n", toys.optargs[TT.toy_obj_file_arg]); | |
297 xprintf(" Size: %llu\t Blocks: %llu\t IO Blocks: %lu\t", TT.toystat->st_size, TT.toystat->st_blocks, TT.toystat->st_blksize); | |
298 xprintf("%s\n", TT.file_type); | |
299 xprintf("Device: %llxh\t Inode: %llu\t Links: %lu\n", TT.toystat->st_dev, TT.toystat->st_ino, TT.toystat->st_nlink); | |
300 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); | |
301 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)); | |
302 }else if(stat_flag_f){ | |
303 // implementation of statfs -f, file system | |
304 if(stat_format) | |
305 print_stat_format(toys.optargs[0], stat_flag_f); | |
306 xprintf(" File: \"%s\"\n", toys.optargs[TT.toy_obj_file_arg]); | |
307 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); | |
308 xprintf("Block Size: %d Fundamental block size: %d\n", TT.toystatfs->f_bsize, TT.toystatfs->f_frsize); | |
309 xprintf("Blocks: Total: %lu\t", TT.toystatfs->f_blocks); | |
310 xprintf("Free: %lu\t", TT.toystatfs->f_bfree); | |
311 xprintf("Available: %lu\n", TT.toystatfs->f_bavail); | |
312 xprintf("Inodes: Total: %lu\t", TT.toystatfs->f_files); | |
313 xprintf("\tFree: %d\n", TT.toystatfs->f_ffree); | |
314 } | |
315 } | |
316 |