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