]> pd.if.org Git - zpackage/blob - zpm-stat.c
add support for notes
[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 'a': /* octal mode */
86                                 printf("%o", (int)buf->st_mode & 07777);
87                                 break;
88                         case 't':
89                                 if (S_ISBLK(buf->st_mode)) {
90                                         printf("block");
91                                 } else if (S_ISCHR(buf->st_mode)) {
92                                         printf("character");
93                                 } else if (S_ISDIR(buf->st_mode)) {
94                                         printf("directory");
95                                 } else if (S_ISFIFO(buf->st_mode)) {
96                                         printf("fifo");
97                                 } else if (S_ISREG(buf->st_mode)) {
98                                         printf("regular");
99                                 } else if (S_ISLNK(buf->st_mode)) {
100                                         printf("symlink");
101                                 } else if (S_ISSOCK(buf->st_mode)) {
102                                         printf("socket");
103                                 } else {
104                                         printf("unknown");
105                                 }
106                                 break;
107                         case 'u': /* handle uid */
108                                 printf("%0d", buf->st_uid);
109                                 break;
110                         case 'U': /* handle username */
111                                 pw = getpwuid(buf->st_uid);
112                                 if (!pw) exit(1);
113                                 printf("%s", pw->pw_name);
114                                 break;
115                         case 'g': /* handle gid */
116                                 printf("%0d", buf->st_gid);
117                                 break;
118                         case 'G': /* handle groupname */
119                                 gr = getgrgid(buf->st_gid);
120                                 if (!gr) exit(1);
121                                 printf("%s", gr->gr_name);
122                                 break;
123                         case 'n':
124                                 printf("%s", filename);
125                                 break;
126                         case '%':
127                                 putchar('%');
128                                 break;
129                         default: /* handle unknown formatting character */
130                                 printf("%c", f.found);
131                                 break;
132                 }
133         }
134         putchar('\n');
135 }
136
137 int main(int ac, char *av[]) {
138         char *fmt = "%y"; /* default stat is mtime */
139         char *timefmt = "%s"; /* default time fmt is unix ts */
140         int errflg = 0;
141         int c;
142         int uselstat = 0;
143
144         while ((c = getopt(ac, av, "lf:t:")) != -1) {
145                 switch(c) {
146                         case 'f':
147                                 fmt = optarg;
148                                 break;
149                         case 't':
150                                 timefmt = optarg;
151                                 break;
152                         case ':':       /* -f or -t without operand */
153                                 fprintf(stderr,
154                                 "Option -%c requires an operand\n", optopt);
155                                 errflg++;
156                                 break;
157                         case 'l':
158                                 uselstat = 1;
159                                 break;
160                         case '?':
161                                 fprintf(stderr,
162                                 "Unrecognized option: '-%c'\n", optopt);
163                                 errflg++;
164                 }
165         }
166         if (errflg) {
167                 fprintf(stderr, "zpm-stat [-f <format>] [-t <timefmt>]\n");
168                 exit(2);
169         }
170         for ( ; optind < ac; optind++) {
171                 struct stat buf;
172                 if (uselstat) {
173                         lstat(av[optind], &buf);
174                 } else {
175                         stat(av[optind], &buf);
176                 }
177                 stat_one(fmt, timefmt, av[optind], &buf);
178         }
179         return 0;
180 }