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