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