Commit 146c2c36 authored by Wayne Davison's avatar Wayne Davison

- Restored some of Matt's suggested logic that I left out, as it

  is needed to get --dry-run to output appropriately.
- Got rid of DR_PINNED from the enum delret.
- Set a flag when we're deleting outside the transfer hierarchy and
  initialize a counter that flist.c will use to count excluded files.
parent 60cc01a6
...@@ -93,17 +93,21 @@ extern int backup_suffix_len; ...@@ -93,17 +93,21 @@ extern int backup_suffix_len;
extern struct file_list *the_file_list; extern struct file_list *the_file_list;
extern struct filter_list_struct server_filter_list; extern struct filter_list_struct server_filter_list;
int ignore_perishable = 0;
int non_perishable_cnt = 0;
static int deletion_count = 0; /* used to implement --max-delete */ static int deletion_count = 0; /* used to implement --max-delete */
/* For calling delete_item() */ /* For calling delete_item() */
#define DEL_RECURSE (1<<1) /* recurse */ #define DEL_RECURSE (1<<1) /* recurse */
#define DEL_DIR_IS_EMPTY (1<<2) /* used by delete_dir_contents() */
enum nonregtype { enum nonregtype {
TYPE_DIR, TYPE_SPECIAL, TYPE_DEVICE, TYPE_SYMLINK TYPE_DIR, TYPE_SPECIAL, TYPE_DEVICE, TYPE_SYMLINK
}; };
enum delret { enum delret {
DR_SUCCESS = 0, DR_FAILURE, DR_AT_LIMIT, DR_PINNED, DR_NOT_EMPTY DR_SUCCESS = 0, DR_FAILURE, DR_AT_LIMIT, DR_NOT_EMPTY
}; };
/* Forward declaration for delete_item(). */ /* Forward declaration for delete_item(). */
...@@ -133,10 +137,12 @@ static enum delret delete_item(char *fname, int mode, char *replace, int flags) ...@@ -133,10 +137,12 @@ static enum delret delete_item(char *fname, int mode, char *replace, int flags)
fname, mode, flags); fname, mode, flags);
} }
if (S_ISDIR(mode) && flags & DEL_RECURSE) { if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
ignore_perishable = 1;
/* If DEL_RECURSE is not set, this just reports emptiness. */
ret = delete_dir_contents(fname, flags); ret = delete_dir_contents(fname, flags);
if (ret == DR_PINNED || ret == DR_NOT_EMPTY ignore_perishable = 0;
|| ret == DR_AT_LIMIT) if (ret == DR_NOT_EMPTY || ret == DR_AT_LIMIT)
goto check_ret; goto check_ret;
/* OK: try to delete the directory. */ /* OK: try to delete the directory. */
} }
...@@ -161,7 +167,7 @@ static enum delret delete_item(char *fname, int mode, char *replace, int flags) ...@@ -161,7 +167,7 @@ static enum delret delete_item(char *fname, int mode, char *replace, int flags)
ret = DR_SUCCESS; ret = DR_SUCCESS;
} else { } else {
if (S_ISDIR(mode) && errno == ENOTEMPTY) { if (S_ISDIR(mode) && errno == ENOTEMPTY) {
rprintf(FINFO, "non-empty directory, %s, not deleted\n", rprintf(FINFO, "cannot delete non-empty directory: %s\n",
fname); fname);
ret = DR_NOT_EMPTY; ret = DR_NOT_EMPTY;
} else if (errno != ENOENT) { } else if (errno != ENOENT) {
...@@ -182,14 +188,15 @@ static enum delret delete_item(char *fname, int mode, char *replace, int flags) ...@@ -182,14 +188,15 @@ static enum delret delete_item(char *fname, int mode, char *replace, int flags)
return ret; return ret;
} }
/* The directory is to be deleted, so delete all its contents. Note /* The directory is about to be deleted: if DEL_RECURSE is given, delete all
* that fname must point to a MAXPATHLEN buffer! (The buffer is used * its contents, otherwise just checks for content. Returns DR_SUCCESS or
* for recursion, but returned unchanged.) * DR_NOT_EMPTY. Note that fname must point to a MAXPATHLEN buffer! (The
* buffer is used for recursion, but returned unchanged.)
*/ */
static enum delret delete_dir_contents(char *fname, int flags) static enum delret delete_dir_contents(char *fname, int flags)
{ {
struct file_list *dirlist; struct file_list *dirlist;
enum delret ret, result; enum delret ret;
unsigned remainder; unsigned remainder;
void *save_filters; void *save_filters;
int j, dlen; int j, dlen;
...@@ -203,7 +210,17 @@ static enum delret delete_dir_contents(char *fname, int flags) ...@@ -203,7 +210,17 @@ static enum delret delete_dir_contents(char *fname, int flags)
dlen = strlen(fname); dlen = strlen(fname);
save_filters = push_local_filters(fname, dlen); save_filters = push_local_filters(fname, dlen);
non_perishable_cnt = 0;
dirlist = get_dirlist(fname, dlen, 0); dirlist = get_dirlist(fname, dlen, 0);
ret = non_perishable_cnt ? DR_NOT_EMPTY : DR_SUCCESS;
if (!dirlist->count)
goto done;
if (!(flags & DEL_RECURSE)) {
ret = DR_NOT_EMPTY;
goto done;
}
p = fname + dlen; p = fname + dlen;
if (dlen != 1 || *fname != '/') if (dlen != 1 || *fname != '/')
...@@ -211,8 +228,7 @@ static enum delret delete_dir_contents(char *fname, int flags) ...@@ -211,8 +228,7 @@ static enum delret delete_dir_contents(char *fname, int flags)
remainder = MAXPATHLEN - (p - fname); remainder = MAXPATHLEN - (p - fname);
/* We do our own recursion, so make delete_item() non-recursive. */ /* We do our own recursion, so make delete_item() non-recursive. */
flags &= ~DEL_RECURSE; flags = (flags & ~DEL_RECURSE) | DEL_DIR_IS_EMPTY;
ret = DR_SUCCESS;
for (j = dirlist->count; j--; ) { for (j = dirlist->count; j--; ) {
struct file_struct *fp = dirlist->files[j]; struct file_struct *fp = dirlist->files[j];
...@@ -223,31 +239,29 @@ static enum delret delete_dir_contents(char *fname, int flags) ...@@ -223,31 +239,29 @@ static enum delret delete_dir_contents(char *fname, int flags)
"mount point, %s, pins parent directory\n", "mount point, %s, pins parent directory\n",
f_name(fp, NULL)); f_name(fp, NULL));
} }
ret = DR_PINNED; ret = DR_NOT_EMPTY;
continue; continue;
} }
strlcpy(p, fp->basename, remainder); strlcpy(p, fp->basename, remainder);
if (S_ISDIR(fp->mode)) {
/* Save stack by recursing to ourself directly. */ /* Save stack by recursing to ourself directly. */
result = delete_dir_contents(fname, flags); if (S_ISDIR(fp->mode)
if (result == DR_PINNED) && delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
ret = result;
else if (result != DR_SUCCESS && ret == DR_SUCCESS)
ret = DR_NOT_EMPTY; ret = DR_NOT_EMPTY;
} if (delete_item(fname, fp->mode, NULL, flags) != DR_SUCCESS)
result = delete_item(fname, fp->mode, NULL, flags);
if (result == DR_PINNED)
ret = result;
else if (result != DR_SUCCESS && ret == DR_SUCCESS)
ret = DR_NOT_EMPTY; ret = DR_NOT_EMPTY;
} }
fname[dlen] = '\0'; fname[dlen] = '\0';
pop_local_filters(save_filters); done:
flist_free(dirlist); flist_free(dirlist);
pop_local_filters(save_filters);
if (ret == DR_NOT_EMPTY) {
rprintf(FINFO, "cannot delete non-empty directory: %s\n",
fname);
}
return ret; return ret;
} }
...@@ -318,7 +332,7 @@ static void delete_in_dir(struct file_list *flist, char *fbuf, ...@@ -318,7 +332,7 @@ static void delete_in_dir(struct file_list *flist, char *fbuf,
continue; continue;
if (fp->flags & FLAG_MOUNT_POINT) { if (fp->flags & FLAG_MOUNT_POINT) {
if (verbose > 1) if (verbose > 1)
rprintf(FINFO, "mount point %s not deleted\n", rprintf(FINFO, "cannot delete mount point: %s\n",
f_name(fp, NULL)); f_name(fp, NULL));
continue; continue;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment