/****************************************************************************** * This file is Copyright 1993 by Philip G. Richards. All Rights Reserved. * See the file README that came with this distribution for permissions on * code usage, copying, and distribution. It comes with absolutely no warranty. * email: ******************************************************************************/ /* ---INFOBEGIN--- * DO NOT DELETE THIS COMMENT BLOCK!!! COMMAND du remote "calculate the remote disk usage" * ---INFOEND--- */ #include "client.h" #include #include "table.h" static int recursive; static int want_all, want_summary; static unsigned int cwdlen; static char *abscwd; static u_long grand_total, filcnt; #define DUBLOCKSIZE 1024 static u_int block_convert(u_int size) { return (size + DUBLOCKSIZE - 1) / DUBLOCKSIZE; } static char * strip_cwd(char *name, int type, int *rel) { if (strncmp(abscwd, name, cwdlen) == 0) { /* it's probably a relative pathname... */ *rel = 1; if (type == 1 && name[cwdlen] == 0) return ""; if (name[cwdlen] == '/') return name + cwdlen; /* oh well, maybe not... */ } *rel = 0; if (name[0] == '/' && name[1] == 0) return ""; return name; } static int add_file_size(char *name, struct stat *sbufp, int depth) { if (want_all || depth == 0) { char *sname; int rel; sname = strip_cwd(name, 0, &rel); ffprintf(STDOUT, "%-7d %s%s\n", block_convert(sbufp->st_size), rel? ".": "", sname); } grand_total += sbufp->st_size; return 0; } static int enter_dir(char *name, int depth, char **pdata) { int *curtotal; /* ** there is no point trying to process this directory if it can't be ** read -- check the directory for readability */ if (!validate_operation(name, LITERAL_DIR | UTIL_DIR)) return -1; /* ** set up some private data space to hold the current file total on ** entry to a directory; this is needed so we can print the total when ** the directory is left */ curtotal = (int *)malloc(sizeof(int)); *curtotal = grand_total; *pdata = (char *)curtotal; return 0; } static void leave_dir(char *name, int depth, char *data) { if (!want_summary || depth == 0) { char *sname; int rel; sname = strip_cwd(name, 1, &rel); ffprintf(STDOUT, "%-7d %s%s/\n", block_convert(grand_total - *((int *)data)), rel? ".": "", sname); } /* data will be free()'d by util_process_file() */ } static int do_du(char *name) { if (!validate_operation(name, UTIL_PROCESS_FILE)) return -1; filcnt++; return util_process_file(name, recursive, 0, add_file_size, enter_dir, leave_dir); } /* ARGSUSED */ int rdu_main(int argc, char *const*argv, char **envp) { int retval, errcnt, ch; static char *here[2] = { ".", 0 }; int want_total; char **argvec; recursive = 0; want_all = 0; want_total = 0; want_summary = 0; optind = 0; opterr = 0; errcnt = 0; #ifdef HAVE_OPTRESET optreset = 1; optind = 1; #endif /* options in the style of GNU du ... well, sort of */ while ((ch = getopt(argc, argv, "acrs")) != EOF) switch (ch) { case 'a': want_all = 1; break; case 'c': want_total = 1; break; case 'r': recursive = MAXRECURSION; break; case 's': want_summary = 1; break; default: errcnt++; break; } if (errcnt > 0) ffprintf(STDERR, "?du usage: du [-[acrs]] [files...]\n"); /* cross validate options */ if (want_summary && want_all) { ffprintf(STDERR, "?du: cannot both summarize and show all entries\n"); errcnt = 1; } /* if any errors in the options, return an error */ if (errcnt > 0) return 1; filcnt = 0; grand_total = 0; /* special case `du' without arguments -- becomes `du .' */ argvec = (optind == argc)? here: argv + optind; /* ** if there is only one argument and no recursion has been requested, ** then allow it to be a directory and we will set recursive to be 1 */ if (recursive == 0 && optind >= argc - 1) recursive = 1; abscwd = util_abs_path(env_dir); cwdlen = strlen(abscwd); /* special case "/" */ if (cwdlen == 1) cwdlen = 0; retval = -util_process_arglist(argvec, do_du); (void)free(abscwd); if (want_total && filcnt > 1) { ffprintf(STDOUT, "--------:------\n"); ffprintf(STDOUT, "%-7d TOTAL\n", block_convert(grand_total)); } client_done(); return retval; }