--- fmirror-0.8.4/fmirror.c.orig 2009-04-07 17:47:43.000000000 +0200 +++ fmirror-0.8.4/fmirror.c 2009-04-07 17:47:43.000000000 +0200 @@ -166,6 +166,7 @@ static int passive = 0; static time_t current_time; static int nodel = 0; +static int maxdel = -1; static int try_reget = 0; /* default is don't try to reget */ static int keep_newer = 0; /* don't download if a newer version exists */ static int reset_times = 0; /* reset access and mod times to remote */ @@ -212,6 +213,7 @@ " -u Username [anonymous]\n" " -v Print version\n" " -V verbosity level [1 suitable for cron jobs, 3 for interactive]\n" +" -X <n> - fmirror can delete up to <n> files\n" " -x Decompressor (executable name _only_) [gzip]\n" " -o Decompressor option [-dc]\n" " -z Compressed dirlist (run decompressor on file-list input)\n\n"; @@ -1695,10 +1697,21 @@ LOG(1, rmfile, ("`%s' is now a (possibly) excluded dir. deleting", prefix)); - if (unlink(prefix)) + if (maxdel) { + if (unlink(prefix)) { LOG(1, failure, ("set_new_directory: unlink(\"%s\") failed: %s", prefix, strerror(errno))); + } else { + if (maxdel>0) + maxdel--; + } + } else { + LOG(1, failure, + ("maxdel exceeded: can't delete %s", + prefix)); + exit(EXIT_FAILURE); + } } } else { unlink_and_mkdir(prefix); @@ -1929,13 +1942,24 @@ free(nam); } else { /* Files are deleted directly */ + if (maxdel) { if (unlink(dent->d_name)) { LOG(0, failure, ("Problems unlinking '%s': %s", dent->d_name, strerror(errno))); closedir(d); return -1; + } else { + if (maxdel>0) + maxdel--; } + } else { + LOG(1, failure, + ("maxdel exceeded: can't delete %s", + dent->d_name)); + closedir(d); + exit(EXIT_FAILURE); + } } } } @@ -1965,6 +1989,7 @@ static int recursive_unlink(const char *filename, struct stat *st) { + int retval=1; /* This function is written in a somewhat special way to handle * directory trees of any depths. Directories are deleted in * depth first order. */ @@ -2006,7 +2031,18 @@ free(old_dir); /* old_dir was malloced */ return rmdir(filename); } - return unlink(filename); + if (maxdel) { + if (!(retval=unlink(filename))) { + if (maxdel>0) + maxdel--; + } + } else { + LOG(1, failure, + ("maxdel exceeded: can't delete %s", + filename)); + exit(EXIT_FAILURE); + } + return retval; } @@ -2022,11 +2058,20 @@ } else { LOG(1, delsymlink, ("- %s ->", p->filename)); } - if (unlink(p->filename)) { + if (maxdel) { + if (unlink(p->filename)) { LOG(0, failure, ("-- ERROR -- unlink '%s': %s", p->filename, strerror(errno))); } else { + if (maxdel>0) + maxdel--; get_file(p); + } + } else { + LOG(1, failure, + ("maxdel exceeded: can't delete %s", + p->filename)); + exit(EXIT_FAILURE); } } else { if (S_ISDIR(st->st_mode)) { @@ -2634,6 +2679,7 @@ OPT_SET_INT(file_or_mask) || OPT_SET_INT(passive) || OPT_SET_INT(nodel) || + OPT_SET_INT(maxdel) || OPT_SET_INT(try_reget) || OPT_SET_INT(use_mdtm) || OPT_SET_INT(remotetz) || @@ -2735,7 +2781,7 @@ { while (1) { int c = getopt(argc, argv, - "A:C:c:D:d:e:f:F:hi:kl:M:m:NO:o:P:p:Rr:s:ST:t:u:vV:x:z:"); + "A:C:c:D:d:e:f:F:hi:kl:M:m:NO:o:P:p:Rr:s:ST:t:u:vV:x:X:z:"); if (c == -1) break; switch (c) { @@ -2748,6 +2794,9 @@ case 'N': nodel = 1; break; + case 'X': + maxdel = strtol(optarg, NULL, 0);; + break; case 'D': dircmd_tz = strdup(optarg); break; --- fmirror-0.8.4/fmirror.1.orig 2009-04-07 17:47:43.000000000 +0200 +++ fmirror-0.8.4/fmirror.1 2009-04-07 17:47:43.000000000 +0200 @@ -30,6 +30,7 @@ [\-u\ username] [\-v] [\-V verbosity] +[\-X maxdel] [\-x\ decompressor] [\-o\ option] [\-z] @@ -230,6 +231,12 @@ interactive use. Default is 3. .TP +.BI "\-X" " maxdel" +Maxdel specifies the maximum number of files to delete during fmirror +invocation. If the number of deleted files exceeds maxdel the +program stops immediately with an error code. + +.TP .BI "\-x" " program" Run .I program @@ -494,6 +501,13 @@ kicked out because the ftp server is full. No equivalent command line option, default value is 15; +.TP +.BI maxdel: " num" +Maxdel specifies the maximum number of files to delete during +fmirror invocation. If the number of deleted files exceeds +.I num +the +program stops immediately with an error code. .TO