X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=client-src%2Fcalcsize.c;h=1336d8d1e553c0296d04c3ec04444d9da719c3ab;hb=94a044f90357edefa6f4ae9f0b1d5885b0e34aee;hp=0f174e8a0e6214b1c7050436e941bdf91d2de576;hpb=94c03cae686e4196a345d72452fda2a5203768ce;p=debian%2Famanda diff --git a/client-src/calcsize.c b/client-src/calcsize.c index 0f174e8..1336d8d 100644 --- a/client-src/calcsize.c +++ b/client-src/calcsize.c @@ -24,28 +24,40 @@ * file named AUTHORS, in the root directory of this distribution. */ /* - * $Id: calcsize.c,v 1.37 2006/03/29 15:45:08 martinea Exp $ + * $Id: calcsize.c,v 1.44 2006/07/25 18:27:56 martinea Exp $ * * traverse directory tree to get backup size estimates + * + * argv[0] is the calcsize program name + * argv[1] is the config name or NOCONFIG */ #include "amanda.h" -#include "statfs.h" +#include "fsusage.h" +#include "version.h" #include "sl.h" +#include "util.h" #define ROUND(n,x) ((x) + (n) - 1 - (((x) + (n) - 1) % (n))) /* -static unsigned long round_function(n, x) -unsigned long n, x; +static off_t +round_function(n, x) + off_t n, + off_t x) { unsigned long remainder = x % n; if (remainder) - x += n-remainder; + x += n - remainder; return x; } */ -#define ST_BLOCKS(s) ((((s).st_blocks * 512) <= (s).st_size) ? (s).st_blocks+1 : ((s).st_size / 512 + (((s).st_size % 512) ? 1 : 0))) +#define ST_BLOCKS(s) \ + (((((off_t)(s).st_blocks * (off_t)512) <= (s).st_size)) ? \ + ((off_t)(s).st_blocks + (off_t)1) : \ + ((s).st_size / (off_t)512 + \ + (off_t)((((s).st_size % (off_t)512) != (off_t)0) ? \ + (off_t)1 : (off_t)0))) #define FILETYPES (S_IFREG|S_IFLNK|S_IFDIR) @@ -62,89 +74,115 @@ struct { int max_inode; int total_dirs; int total_files; - long total_size; - long total_size_name; + off_t total_size; + off_t total_size_name; } dumpstats[MAXDUMPS]; time_t dumpdate[MAXDUMPS]; int dumplevel[MAXDUMPS]; int ndumps; -void (*add_file_name) P((int, char *)); -void (*add_file) P((int, struct stat *)); -long (*final_size) P((int, char *)); +void (*add_file_name)(int, char *); +void (*add_file)(int, struct stat *); +off_t (*final_size)(int, char *); + +int main(int, char **); +void traverse_dirs(char *, char *); -int main P((int, char **)); -void traverse_dirs P((char *, char *)); +void add_file_name_dump(int, char *); +void add_file_dump(int, struct stat *); +off_t final_size_dump(int, char *); -void add_file_name_dump P((int, char *)); -void add_file_dump P((int, struct stat *)); -long final_size_dump P((int, char *)); +void add_file_name_star(int, char *); +void add_file_star(int, struct stat *); +off_t final_size_star(int, char *); -void add_file_name_gnutar P((int, char *)); -void add_file_gnutar P((int, struct stat *)); -long final_size_gnutar P((int, char *)); +void add_file_name_gnutar(int, char *); +void add_file_gnutar(int, struct stat *); +off_t final_size_gnutar(int, char *); -void add_file_name_unknown P((int, char *)); -void add_file_unknown P((int, struct stat *)); -long final_size_unknown P((int, char *)); +void add_file_name_unknown(int, char *); +void add_file_unknown(int, struct stat *); +off_t final_size_unknown(int, char *); -sl_t *calc_load_file P((char *filename)); -int calc_check_exclude P((char *filename)); +sl_t *calc_load_file(char *filename); +int calc_check_exclude(char *filename); +int use_star_excl = 0; int use_gtar_excl = 0; sl_t *include_sl=NULL, *exclude_sl=NULL; -int main(argc, argv) -int argc; -char **argv; +int +main( + int argc, + char ** argv) { #ifdef TEST /* standalone test to ckeck wether the calculated file size is ok */ struct stat finfo; int i; - unsigned long dump_total=0, gtar_total=0; + off_t dump_total = (off_t)0; + off_t gtar_total = (off_t)0; char *d; int l, w; + /* + * Configure program for internationalization: + * 1) Only set the message locale for now. + * 2) Set textdomain for all amanda related programs to "amanda" + * We don't want to be forced to support dozens of message catalogs. + */ + setlocale(LC_MESSAGES, "C"); + textdomain("amanda"); + safe_fd(-1, 0); set_pname("calcsize"); + dbopen(NULL); + /* Don't die when child closes pipe */ signal(SIGPIPE, SIG_IGN); if (argc < 2) { - fprintf(stderr,"Usage: %s file[s]\n",argv[0]); + g_fprintf(stderr,_("Usage: %s file[s]\n"),argv[0]); return 1; } for(i=1; i 0) { amname = *argv; + qamname = quote_string(amname); argc--, argv++; - } else + } else { error("missing "); + /*NOTREACHED*/ + } /* the toplevel directory name to search from */ if (argc > 0) { dirname = *argv; argc--, argv++; - } else + } else { error("missing "); + /*NOTREACHED*/ + } if ((argc > 1) && strcmp(*argv,"-X") == 0) { argv++; - if (!use_gtar_excl) { + if (!(use_gtar_excl || use_star_excl)) { error("exclusion specification not supported"); - return 1; + /*NOTREACHED*/ } filename = stralloc(*argv); + qfilename = quote_string(filename); if (access(filename, R_OK) != 0) { - fprintf(stderr,"Cannot open exclude file %s\n",filename); - use_gtar_excl = 0; + g_fprintf(stderr,"Cannot open exclude file %s\n", qfilename); + use_gtar_excl = use_star_excl = 0; } else { - exclude_sl = calc_load_file(filename); + exclude_sl = calc_load_file(filename); + if (!exclude_sl) { + g_fprintf(stderr,"Cannot open exclude file %s: %s\n", qfilename, + strerror(errno)); + use_gtar_excl = use_star_excl = 0; + } } + amfree(qfilename); amfree(filename); argc -= 2; argv++; - } else - use_gtar_excl = 0; + } else { + use_gtar_excl = use_star_excl = 0; + } if ((argc > 1) && strcmp(*argv,"-I") == 0) { argv++; filename = stralloc(*argv); + qfilename = quote_string(filename); if (access(filename, R_OK) != 0) { - fprintf(stderr,"Cannot open include file %s\n",filename); - use_gtar_excl = 0; + g_fprintf(stderr,"Cannot open include file %s\n", qfilename); + use_gtar_excl = use_star_excl = 0; } else { - include_sl = calc_load_file(filename); + include_sl = calc_load_file(filename); + if (!include_sl) { + g_fprintf(stderr,"Cannot open include file %s: %s\n", qfilename, + strerror(errno)); + use_gtar_excl = use_star_excl = 0; + } } + amfree(qfilename); amfree(filename); argc -= 2; argv++; @@ -253,8 +320,10 @@ char **argv; } } - if(argc) + if(argc) { error("leftover arg \"%s\", expected and ", *argv); + /*NOTREACHED*/ + } if(is_empty_sl(include_sl)) { traverse_dirs(dirname,"."); @@ -275,20 +344,17 @@ char **argv; amflock(1, "size"); - lseek(1, (off_t)0, SEEK_END); - - fprintf(stderr, "%s %d SIZE %ld\n", - amname, dumplevel[i], final_size(i, dirname)); - fflush(stdout); + dbprintf("calcsize: %s %d SIZE %lld\n", + qamname, dumplevel[i], + (long long)final_size(i, dirname)); + g_fprintf(stderr, "%s %d SIZE %lld\n", + qamname, dumplevel[i], + (long long)final_size(i, dirname)); + fflush(stderr); amfunlock(1, "size"); } - - malloc_size_2 = malloc_inuse(&malloc_hist_2); - - if(malloc_size_1 != malloc_size_2) { - malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2); - } + amfree(qamname); return 0; #endif @@ -299,10 +365,10 @@ char **argv; */ #if !defined(HAVE_BASENAME) && defined(BUILTIN_EXCLUDE_SUPPORT) -static char *basename P((char *)); -static char *basename(file) -char *file; +static char * +basename( + char * file) { char *cp; @@ -312,29 +378,34 @@ char *file; } #endif -void push_name P((char *str)); -char *pop_name P((void)); +void push_name(char *str); +char *pop_name(void); -void traverse_dirs(parent_dir, include) -char *parent_dir; -char *include; +void +traverse_dirs( + char * parent_dir, + char * include) { DIR *d; struct dirent *f; struct stat finfo; char *dirname, *newname = NULL; char *newbase = NULL; - dev_t parent_dev = 0; + dev_t parent_dev = (dev_t)0; int i; - int l; - int parent_len; - int has_exclude = !is_empty_sl(exclude_sl) && use_gtar_excl; + size_t l; + size_t parent_len; + int has_exclude; char *aparent; - if(parent_dir == NULL || include == NULL) return; + if(parent_dir == NULL || include == NULL) + return; + has_exclude = !is_empty_sl(exclude_sl) && (use_gtar_excl || use_star_excl); aparent = vstralloc(parent_dir, "/", include, NULL); + /* We (may) need root privs for the *stat() calls here. */ + set_root_privs(1); if(stat(parent_dir, &finfo) != -1) parent_dev = finfo.st_dev; @@ -342,7 +413,7 @@ char *include; push_name(aparent); - for(dirname = pop_name(); dirname; free(dirname), dirname = pop_name()) { + for(; (dirname = pop_name()) != NULL; free(dirname)) { if(has_exclude && calc_check_exclude(dirname+parent_len+1)) { continue; } @@ -368,7 +439,7 @@ char *include; newname = newstralloc2(newname, newbase, f->d_name); if(lstat(newname, &finfo) == -1) { - fprintf(stderr, "%s/%s: %s\n", + g_fprintf(stderr, "%s/%s: %s\n", dirname, f->d_name, strerror(errno)); continue; } @@ -390,7 +461,7 @@ char *include; int is_excluded = -1; for(i = 0; i < ndumps; i++) { add_file_name(i, newname); - if(is_file && finfo.st_ctime >= dumpdate[i]) { + if(is_file && (time_t)finfo.st_ctime >= dumpdate[i]) { if(has_exclude) { if(is_excluded == -1) @@ -419,24 +490,30 @@ char *include; perror(dirname); #endif } + + /* drop root privs -- we're done with the permission-sensitive calls */ + set_root_privs(0); + amfree(newbase); amfree(newname); amfree(aparent); } -void push_name(str) -char *str; +void +push_name( + char * str) { Name *newp; - newp = alloc(sizeof(*newp)); + newp = alloc(SIZEOF(*newp)); newp->str = stralloc(str); newp->next = name_stack; name_stack = newp; } -char *pop_name() +char * +pop_name(void) { Name *newp = name_stack; char *str; @@ -466,44 +543,52 @@ char *pop_name() * requirements for files with holes, nor the dumping of directories that * are not themselves modified. */ -void add_file_name_dump(level, name) -int level; -char *name; +void +add_file_name_dump( + int level, + char * name) { + (void)level; /* Quiet unused parameter warning */ + (void)name; /* Quiet unused parameter warning */ + return; } -void add_file_dump(level, sp) -int level; -struct stat *sp; +void +add_file_dump( + int level, + struct stat * sp) { /* keep the size in kbytes, rounded up, plus a 1k header block */ if((sp->st_mode & S_IFMT) == S_IFREG || (sp->st_mode & S_IFMT) == S_IFDIR) - dumpstats[level].total_size += (ST_BLOCKS(*sp) + 1)/2 + 1; + dumpstats[level].total_size += + (ST_BLOCKS(*sp) + (off_t)1) / (off_t)2 + (off_t)1; } -long final_size_dump(level, topdir) -int level; -char *topdir; +off_t +final_size_dump( + int level, + char * topdir) { - generic_fs_stats_t stats; - int mapsize; + struct fs_usage fsusage; + off_t mapsize; char *s; /* calculate the map sizes */ s = stralloc2(topdir, "/."); - if(get_fs_stats(s, &stats) == -1) { + if(get_fs_usage(s, NULL, &fsusage) == -1) { error("statfs %s: %s", s, strerror(errno)); + /*NOTREACHED*/ } amfree(s); - mapsize = (stats.files + 7) / 8; /* in bytes */ - mapsize = (mapsize + 1023) / 1024; /* in kbytes */ + mapsize = (fsusage.fsu_files + (off_t)7) / (off_t)8; /* in bytes */ + mapsize = (mapsize + (off_t)1023) / (off_t)1024; /* in kbytes */ /* the dump contains three maps plus the files */ - return 3*mapsize + dumpstats[level].total_size; + return (mapsize * (off_t)3) + dumpstats[level].total_size; } /* @@ -517,29 +602,37 @@ char *topdir; * * As with DUMP, we only need a reasonable estimate, not an exact figure. */ -void add_file_name_gnutar(level, name) -int level; -char *name; +void +add_file_name_gnutar( + int level, + char * name) { -/* dumpstats[level].total_size_name += strlen(name) + 64;*/ - dumpstats[level].total_size += 1; + (void)name; /* Quiet unused parameter warning */ + +/* dumpstats[level].total_size_name += strlen(name) + 64;*/ + dumpstats[level].total_size += (off_t)1; } -void add_file_gnutar(level, sp) -int level; -struct stat *sp; +void +add_file_gnutar( + int level, + struct stat * sp) { /* the header takes one additional block */ dumpstats[level].total_size += ST_BLOCKS(*sp); } -long final_size_gnutar(level, topdir) -int level; -char *topdir; +off_t +final_size_gnutar( + int level, + char * topdir) { + (void)topdir; /* Quiet unused parameter warning */ + /* divide by two to get kbytes, rounded up */ /* + 4 blocks for security */ - return (dumpstats[level].total_size + 5 + (dumpstats[level].total_size_name/512)) / 2; + return (dumpstats[level].total_size + (off_t)5 + + (dumpstats[level].total_size_name/(off_t)512)) / (off_t)2; } /* @@ -549,42 +642,57 @@ char *topdir; * Here we'll just add up the file sizes and output that. */ -void add_file_name_unknown(level, name) -int level; -char *name; +void +add_file_name_unknown( + int level, + char * name) { + (void)level; /* Quiet unused parameter warning */ + (void)name; /* Quiet unused parameter warning */ + return; } -void add_file_unknown(level, sp) -int level; -struct stat *sp; +void +add_file_unknown( + int level, + struct stat * sp) { /* just add up the block counts */ if((sp->st_mode & S_IFMT) == S_IFREG || (sp->st_mode & S_IFMT) == S_IFDIR) dumpstats[level].total_size += ST_BLOCKS(*sp); } -long final_size_unknown(level, topdir) -int level; -char *topdir; +off_t +final_size_unknown( + int level, + char * topdir) { + (void)topdir; /* Quiet unused parameter warning */ + /* divide by two to get kbytes, rounded up */ - return (dumpstats[level].total_size + 1) / 2; + return (dumpstats[level].total_size + (off_t)1) / (off_t)2; } /* * ========================================================================= */ -sl_t *calc_load_file(filename) -char *filename; +sl_t * +calc_load_file( + char * filename) { char pattern[1025]; - sl_t *sl_list = new_sl(); + sl_t *sl_list; FILE *file = fopen(filename, "r"); + if (!file) { + return NULL; + } + + sl_list = new_sl(); + while(fgets(pattern, 1025, file)) { if(strlen(pattern)>0 && pattern[strlen(pattern)-1] == '\n') pattern[strlen(pattern)-1] = '\0'; @@ -595,8 +703,9 @@ char *filename; return sl_list; } -int calc_check_exclude(filename) -char *filename; +int +calc_check_exclude( + char * filename) { sle_t *an_exclude; if(is_empty_sl(exclude_sl)) return 0;