3 * cat startpoints.list | summer >data.list
4 * summer startpoints... >data.list
5 * prints md5sum of data-list to stderr
11 #include <sys/types.h>
22 #include "nettle/md5-compat.h"
28 static int quiet=0, hidectime=0, hideatime=0;
29 static int hidedirsizelinkcount=0, hidelinkmtime=0;
30 static int filenamefieldsep=' ';
33 static void fn_escaped(FILE *f, const char *fn) {
36 if (c>=33 && c<=126 && c!='\\') putc(c,f);
37 else fprintf(f,"\\x%02x",(int)(unsigned char)c);
41 static void add_pr(int *pr, int printf_ret) {
42 if (printf_ret == EOF) return;
46 static void vproblemx(const char *path, int padto, int per,
47 const char *fmt, va_list al) {
50 if (errfile==stderr) fputs("summer: error: ",stderr);
51 else add_pr(&pr, fprintf(errfile,"\\["));
53 add_pr(&pr, vfprintf(errfile,fmt,al));
54 if (per) add_pr(&pr, fprintf(errfile,": %s",strerror(e)));
56 if (errfile==stderr) {
58 fn_escaped(stderr,path);
63 add_pr(&pr, printf("]"));
69 static void problem_e(const char *path, int padto, const char *fmt, ...) {
72 vproblemx(path,padto,1,fmt,al);
76 static void problem(const char *path, int padto, const char *fmt, ...) {
79 vproblemx(path,padto,0,fmt,al);
83 static void csum_file(const char *path) {
87 unsigned char digest[16];
92 if (!f) { problem_e(path,sizeof(digest)*2,"open"); return; }
96 r= fread(db,1,sizeof(db),f);
98 problem_e(path,sizeof(digest)*2,"read");
101 if (!r) { assert(feof(f)); break; }
104 MD5Final(digest,&mc);
105 if (fclose(f)) { problem_e(path,sizeof(digest)*2,"close"); return; }
107 for (i=0; i<sizeof(digest); i++)
108 printf("%02x", digest[i]);
111 static void csum_dev(int cb, const struct stat *stab) {
112 printf("%c 0x%08lx %3lu %3lu %3lu %3lu ", cb,
113 (unsigned long)stab->st_rdev,
114 ((unsigned long)stab->st_rdev & 0x0ff000000U) >> 24,
115 ((unsigned long)stab->st_rdev & 0x000ff0000U) >> 16,
116 ((unsigned long)stab->st_rdev & 0x00000ff00U) >> 8,
117 ((unsigned long)stab->st_rdev & 0x0000000ffU) >> 0);
120 static void csum_str(const char *s) {
121 printf("%-*s", CSUMXL, s);
126 static int item(const char *path, const struct stat *stab,
127 int flag, struct FTW *ftws) {
128 char linktarg[MAXFN+1];
134 if (S_ISREG(stab->st_mode)) csum_file(path);
135 else if (S_ISDIR(stab->st_mode)) csum_str("dir");
136 else if (S_ISCHR(stab->st_mode)) csum_dev('c',stab);
137 else if (S_ISBLK(stab->st_mode)) csum_dev('b',stab);
138 else if (S_ISFIFO(stab->st_mode)) csum_str("pipe");
139 else if (S_ISLNK(stab->st_mode)) csum_str("link");
140 else if (S_ISSOCK(stab->st_mode)) csum_str("sock");
141 else problem(path,CSUMXL,"badobj: 0x%lx", (unsigned long)stab->st_mode);
146 problem_e(path,CSUMXL,"inaccessible");
150 problem(path,CSUMXL,"ftw flag 0x%x: %s",flag);
153 if (S_ISLNK(stab->st_mode)) {
156 r= readlink(path, linktarg, sizeof(linktarg)-1);
157 if (r==sizeof(linktarg)) { problem(path,-1,"readlink too big"); r=-1; }
158 else if (r<0) { problem_e(path,-1,"readlink"); }
159 else assert(r<sizeof(linktarg));
161 if (r<0) strcpy(linktarg,"\\?");
165 if (S_ISDIR(stab->st_mode) && hidedirsizelinkcount)
166 printf(" %10s %4s","dir","dir");
169 (unsigned long)stab->st_size,
170 (int)stab->st_nlink);
172 printf(" %4o %10ld %10ld",
173 (unsigned)stab->st_mode & 07777U,
174 (unsigned long)stab->st_uid,
175 (unsigned long)stab->st_gid);
179 (unsigned long)stab->st_atime);
181 if (S_ISLNK(stab->st_mode) && hidelinkmtime)
182 printf(" %10s","link");
185 (unsigned long)stab->st_mtime);
189 (unsigned long)stab->st_ctime);
190 putchar(filenamefieldsep);
191 fn_escaped(stdout, path);
193 if (S_ISLNK(stab->st_mode)) {
195 fn_escaped(stdout, linktarg);
199 if (ferror(stdout)) { perror("summer: stdout"); exit(12); }
203 static void process(const char *startpoint) {
206 fprintf(stderr,"summer: processing: %s\n",startpoint);
207 r= nftw(startpoint, item, MAXDEPTH, FTW_MOUNT|FTW_PHYS);
208 if (r) { fprintf(stderr, "summer: nftw failed: %s: %s\n",
209 strerror(errno), startpoint); exit(4); }
212 static void from_stdin(void) {
218 fprintf(stderr, "summer: processing stdin lines as startpoints\n");
220 s= fgets(buf,sizeof(buf),stdin);
221 if (ferror(stdin)) { perror("summer: stdin"); exit(12); }
222 if (!s) { if (feof(stdin)) return; else abort(); }
225 if (buf[l-1]!='\n') { fprintf(stderr,"summer: line too long\n"); exit(8); }
231 int main(int argc, const char *const *argv) {
237 if ((arg=argv[1]) && *arg++=='-') {
242 "summer: usage: summer startpoint... >data.list\n"
243 " cat startpoints.list | summer >data.list\n");
249 filenamefieldsep= '\t';
252 hidedirsizelinkcount= 1;
267 fprintf(stderr,"summer: bad usage, try -h\n");
278 fprintf(stderr, "summer: processing command line args as startpoints\n");
279 while ((arg=*++argv)) {
283 if (ferror(stdout) || fclose(stdout)) {
284 perror("summer: stdout (at end)"); exit(12);
287 fputs("summer: done.\n", stderr);