]> pd.if.org Git - zpackage/blob - zpm-stat.c
add zpm-stat command for a portable stat interface
[zpackage] / zpm-stat.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/stat.h>
5 #include <pwd.h>
6 #include <grp.h>
7
8 #include "zpm.h"
9
10 /*
11  * a generic printf style format string parser
12  * takes a character pointer, returns pointer to next non
13  * parsed character,  next token, optionally
14  * does a callback, fills in a format struct
15  */
16
17 #if 0
18 char *fmt;
19 struct format f;
20
21 while (*fmt) {
22         fmt = parse_format_str(fmt, &f);
23         if (!f.found) break; /* done */
24         if (!f.flags) {
25                 /* literal/noformat */
26                 putchar(f.found); /* or whatever */
27                 continue;
28         }
29         switch (f.found) {
30                 case 'a': /* handle %a */
31                         break;
32                 default: /* handle unknown formatting character */
33                         break;
34         }
35 }
36 #endif
37
38 struct format_string {
39         int found; /* the 'd' in '%d' */
40         unsigned flags; /* 1 = found, 0 = none found */
41 };
42
43 char *format_string_parse(char *s, struct format_string *f) {
44         f->found = 0;
45         f->flags = 0;
46
47         if (!*s) return s; /* done */
48
49         /* literal non-format specifier */
50         if (*s != '%') {
51                 f->found = *s++;
52                 return s;
53         }
54         s++;
55
56         f->flags = 1;
57         f->found = *s++;
58         return s;
59 }
60
61 void stat_one(char *fmt, char *timefmt, char *filename) {
62         struct stat buf;
63         struct tm *tm;
64         char timestr[1024];
65         struct format_string f;
66         struct passwd *pw;
67         struct group *gr;
68
69         stat(filename, &buf);
70
71         while (*fmt) {
72                 fmt = format_string_parse(fmt, &f);
73                 if (!f.found) break; /* done */
74                 if (!f.flags) {
75                         /* literal/noformat */
76                         putchar(f.found); /* or whatever */
77                         continue;
78                 }
79                 switch (f.found) {
80                         case 'y': /* handle mtime */
81                                 tm = gmtime(&buf.st_mtime);
82                                 strftime(timestr, 1023, timefmt, tm);
83                                 timestr[1023] = 0;
84                                 printf("%s", timestr);
85                                 break;
86                         case 'a': /* octal mode */
87                                 printf("%o", (int)buf.st_mode & 07777);
88                                 break;
89                         case 'u': /* handle uid */
90                                 printf("%0d", buf.st_uid);
91                                 break;
92                         case 'U': /* handle username */
93                                 pw = getpwuid(buf.st_uid);
94                                 if (!pw) exit(1);
95                                 printf("%s", pw->pw_name);
96                                 break;
97                         case 'g': /* handle gid */
98                                 printf("%0d", buf.st_gid);
99                                 break;
100                         case 'G': /* handle groupname */
101                                 gr = getgrgid(buf.st_gid);
102                                 if (!gr) exit(1);
103                                 printf("%s", gr->gr_name);
104                                 break;
105                         default: /* handle unknown formatting character */
106                                 printf("%c", f.found);
107                                 break;
108                 }
109         }
110         putchar('\n');
111 }
112
113 int main(int ac, char *av[]) {
114         char *fmt = "%y"; /* default stat is mtime */
115         char *timefmt = "%s"; /* default time fmt is unix ts */
116         int errflg = 0;
117         int c;
118
119         while ((c = getopt(ac, av, "f:t:")) != -1) {
120                 switch(c) {
121                         case 'f':
122                                 fmt = optarg;
123                                 break;
124                         case 't':
125                                 timefmt = optarg;
126                                 break;
127                         case ':':       /* -f or -t without operand */
128                                 fprintf(stderr,
129                                 "Option -%c requires an operand\n", optopt);
130                                 errflg++;
131                                 break;
132                         case '?':
133                                 fprintf(stderr,
134                                 "Unrecognized option: '-%c'\n", optopt);
135                                 errflg++;
136                 }
137         }
138         if (errflg) {
139                 fprintf(stderr, "zpm-stat [-f <format>] [-t <timefmt>]");
140                 exit(2);
141         }
142         for ( ; optind < ac; optind++) {
143                 stat_one(fmt, timefmt, av[optind]);
144         }
145         return 0;
146 }