X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-utils.git;a=blobdiff_plain;f=cprogs%2Fsummer.c;h=762b5d68812ac0b5e20d86ce65745bb40b6a5e06;hp=2c4f9df197995beba1cf04d10ffbed101459906d;hb=1e17ba9014e80fc58acfa88b20e8fd2744d994d5;hpb=11633c3162005c1ce29fdd88b5db4d08a104d07a diff --git a/cprogs/summer.c b/cprogs/summer.c index 2c4f9df..762b5d6 100644 --- a/cprogs/summer.c +++ b/cprogs/summer.c @@ -1,9 +1,29 @@ /* + * summer - program for summarising (with md5 checksums) filesystem trees + * * usage: * cat startpoints.list | summer >data.list * summer startpoints... >data.list * prints md5sum of data-list to stderr */ +/* + * Copyright (C) 2003,2006-2007 Ian Jackson + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3, + * or (at your option) any later version. + * + * This is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, consult the Free Software + * Foundation's website at www.fsf.org, or the GNU Project website at + * www.gnu.org. + */ #define _GNU_SOURCE @@ -26,11 +46,13 @@ #define MAXDEPTH 1024 #define CSUMXL 32 -static int quiet=0, hidectime=0, hideatime=0; -static int hidedirsize=0, hidelinkmtime=0; +static int quiet=0, hidectime=0, hideatime=0, hidemtime=0; +static int hidedirsize=0, hidelinkmtime=0, hidextime=0, onefilesystem=0; static int filenamefieldsep=' '; static FILE *errfile; +#define nodeflag_fsvalid 1u + static void malloc_fail(void) { perror("summer: alloc failed"); exit(12); } static void *mmalloc(size_t sz) { @@ -141,6 +163,28 @@ static void linktargpath(const char *linktarg) { fn_escaped(stdout, linktarg); } +static void pu10(void) { printf(" %10s", "?"); } + +#define PTIME(stab, memb) ((stab) ? ptime((stab), (stab)->memb) : pu10()) + +static void ptime(const struct stat *stab, unsigned long val) { + const char *instead; + + if (!hidextime) goto justprint; + else if (S_ISCHR(stab->st_mode)) instead= "char"; + else if (S_ISBLK(stab->st_mode)) instead= "block"; + else if (S_ISLNK(stab->st_mode)) instead= "link"; + else if (S_ISSOCK(stab->st_mode)) instead= "sock"; + else if (S_ISFIFO(stab->st_mode)) instead= "pipe"; + else { + justprint: + printf(" %10lu", val); + return; + } + + printf(" %10s",instead); +} + struct hardlink { dev_t dev; ino_t ino; @@ -148,22 +192,20 @@ struct hardlink { }; static void *hardlinks; -static void pu10(void) { printf(" %10s", "?"); } - static int hardlink_compar(const void *av, const void *bv) { const struct hardlink *a=av, *b=bv; if (a->ino != b->ino) return b->ino - a->ino; return b->dev - a->dev; } -static void recurse(const char *path); +static void recurse(const char *path, unsigned nodeflags, dev_t fs); -static void node(const char *path) { +static void node(const char *path, unsigned nodeflags, dev_t fs) { char linktarg[MAXFN+1]; struct hardlink *foundhl; const struct stat *stab; struct stat stabuf; - int r; + int r, mountpoint=0; r= lstat(path, &stabuf); stab= r ? 0 : &stabuf; @@ -185,15 +227,22 @@ static void node(const char *path) { } } + if (stab) { + if ((nodeflags & nodeflag_fsvalid) && stab->st_dev != fs) + mountpoint= 1; + fs= stab->st_dev; + nodeflags |= nodeflag_fsvalid; + } + if (!stab) problem_e(path,CSUMXL,"inaccessible"); else if (foundhl) csum_str("hardlink"); else if (S_ISREG(stab->st_mode)) csum_file(path); - else if (S_ISDIR(stab->st_mode)) csum_str("dir"); else if (S_ISCHR(stab->st_mode)) csum_dev('c',stab); else if (S_ISBLK(stab->st_mode)) csum_dev('b',stab); else if (S_ISFIFO(stab->st_mode)) csum_str("pipe"); else if (S_ISLNK(stab->st_mode)) csum_str("symlink"); else if (S_ISSOCK(stab->st_mode)) csum_str("sock"); + else if (S_ISDIR(stab->st_mode)) csum_str(mountpoint ? "mountpoint" : "dir"); else problem(path,CSUMXL,"badobj: 0x%lx", (unsigned long)stab->st_mode); if (stab && S_ISLNK(stab->st_mode)) { @@ -221,31 +270,19 @@ static void node(const char *path) { printf(" %10s %4s %10s %10s", "?","?","?","?"); } - if (!hideatime) { - if (stab) - printf(" %10lu", - (unsigned long)stab->st_atime); - else - pu10(); - } + if (!hideatime) + PTIME(stab, st_atime); - if (stab) - if (S_ISLNK(stab->st_mode) && hidelinkmtime) + if (!hidemtime) { + if (stab && S_ISLNK(stab->st_mode) && hidelinkmtime) printf(" %10s","link"); else - printf(" %10lu", - (unsigned long)stab->st_mtime); - else - pu10(); - - if (!hidectime) { - if (stab) - printf(" %10lu", - (unsigned long)stab->st_ctime); - else - pu10(); + PTIME(stab, st_mtime); } + if (!hidectime) + PTIME(stab, st_ctime); + putchar(filenamefieldsep); fn_escaped(stdout, path); @@ -256,14 +293,14 @@ static void node(const char *path) { if (ferror(stdout)) { perror("summer: stdout"); exit(12); } - if (stab && S_ISDIR(stab->st_mode)) - recurse(path); + if (stab && S_ISDIR(stab->st_mode) && !(mountpoint && onefilesystem)) + recurse(path, nodeflags, fs); } static void process(const char *startpoint) { if (!quiet) fprintf(stderr,"summer: processing: %s\n",startpoint); - node(startpoint); + node(startpoint, 0,0); tdestroy(hardlinks,free); hardlinks= 0; } @@ -282,17 +319,15 @@ static int recurse_filter(const struct dirent *de) { return 1; } -static int recurse_compar(const void *av, const void *bv) { - const struct dirent *const *a=av, *const *b=bv; +static int recurse_compar(const struct dirent **a, const struct dirent **b) { return strcmp((*a)->d_name, (*b)->d_name); } -static void recurse(const char *path_or_buf) { +static void recurse(const char *path_or_buf, unsigned nodeflags, dev_t fs) { static char *buf; static int buf_allocd; struct dirent **namelist, *const *de; - char *subpathp; const char *path_or_0= path_or_buf==buf ? 0 : path_or_buf; int nentries, pathl, esave, buf_want, i; @@ -311,18 +346,16 @@ static void recurse(const char *path_or_buf) { if (path_or_0) strcpy(buf,path_or_0); buf[pathl]= '/'; - subpathp= buf+pathl+1; + pathl++; if (nentries < 0) { - strcpy(subpathp,"\\?"); errno= esave; - problem_e(buf,-1,"scandir failed"); + buf[pathl]= 0; errno= esave; + problem_e(buf,CSUMXL+72,"scandir failed"); + fn_escaped(stdout,buf); putchar('\n'); return; } for (i=0, de=namelist; id_name); - strcpy(subpathp, (*de)->d_name); - node(buf); + strcpy(buf+pathl, (*de)->d_name); + node(buf, nodeflags, fs); free(*de); } free(namelist); @@ -353,7 +386,7 @@ int main(int argc, const char *const *argv) { errfile= stderr; - if ((arg=argv[1]) && *arg++=='-') { + while ((arg=argv[1]) && *arg++=='-') { while ((c=*arg++)) { switch (c) { case 'h': @@ -373,12 +406,21 @@ int main(int argc, const char *const *argv) { case 'b': hidelinkmtime= 1; break; + case 'B': + hidextime= 1; + break; + case 'x': + onefilesystem= 1; + break; case 'C': hidectime= 1; break; case 'A': hideatime= 1; break; + case 'M': + hidemtime= 1; + break; case 'f': errfile= stdout; break;