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