File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / delete.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 14 07:51:14 2013 UTC (10 years, 8 months ago) by misho
Branches: rsync, MAIN
CVS tags: RSYNC3_1_0, HEAD
v 3.1.0

    1: /*
    2:  * Deletion routines used in rsync.
    3:  *
    4:  * Copyright (C) 1996-2000 Andrew Tridgell
    5:  * Copyright (C) 1996 Paul Mackerras
    6:  * Copyright (C) 2002 Martin Pool <mbp@samba.org>
    7:  * Copyright (C) 2003-2013 Wayne Davison
    8:  *
    9:  * This program is free software; you can redistribute it and/or modify
   10:  * it under the terms of the GNU General Public License as published by
   11:  * the Free Software Foundation; either version 3 of the License, or
   12:  * (at your option) any later version.
   13:  *
   14:  * This program is distributed in the hope that it will be useful,
   15:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17:  * GNU General Public License for more details.
   18:  *
   19:  * You should have received a copy of the GNU General Public License along
   20:  * with this program; if not, visit the http://fsf.org website.
   21:  */
   22: 
   23: #include "rsync.h"
   24: 
   25: extern int am_root;
   26: extern int make_backups;
   27: extern int max_delete;
   28: extern char *backup_dir;
   29: extern char *backup_suffix;
   30: extern int backup_suffix_len;
   31: extern struct stats stats;
   32: 
   33: int ignore_perishable = 0;
   34: int non_perishable_cnt = 0;
   35: int skipped_deletes = 0;
   36: 
   37: static inline int is_backup_file(char *fn)
   38: {
   39: 	int k = strlen(fn) - backup_suffix_len;
   40: 	return k > 0 && strcmp(fn+k, backup_suffix) == 0;
   41: }
   42: 
   43: /* The directory is about to be deleted: if DEL_RECURSE is given, delete all
   44:  * its contents, otherwise just checks for content.  Returns DR_SUCCESS or
   45:  * DR_NOT_EMPTY.  Note that fname must point to a MAXPATHLEN buffer!  (The
   46:  * buffer is used for recursion, but returned unchanged.)
   47:  */
   48: static enum delret delete_dir_contents(char *fname, uint16 flags)
   49: {
   50: 	struct file_list *dirlist;
   51: 	enum delret ret;
   52: 	unsigned remainder;
   53: 	void *save_filters;
   54: 	int j, dlen;
   55: 	char *p;
   56: 
   57: 	if (DEBUG_GTE(DEL, 3)) {
   58: 		rprintf(FINFO, "delete_dir_contents(%s) flags=%d\n",
   59: 			fname, flags);
   60: 	}
   61: 
   62: 	dlen = strlen(fname);
   63: 	save_filters = push_local_filters(fname, dlen);
   64: 
   65: 	non_perishable_cnt = 0;
   66: 	dirlist = get_dirlist(fname, dlen, 0);
   67: 	ret = non_perishable_cnt ? DR_NOT_EMPTY : DR_SUCCESS;
   68: 
   69: 	if (!dirlist->used)
   70: 		goto done;
   71: 
   72: 	if (!(flags & DEL_RECURSE)) {
   73: 		ret = DR_NOT_EMPTY;
   74: 		goto done;
   75: 	}
   76: 
   77: 	p = fname + dlen;
   78: 	if (dlen != 1 || *fname != '/')
   79: 		*p++ = '/';
   80: 	remainder = MAXPATHLEN - (p - fname);
   81: 
   82: 	/* We do our own recursion, so make delete_item() non-recursive. */
   83: 	flags = (flags & ~(DEL_RECURSE|DEL_MAKE_ROOM|DEL_NO_UID_WRITE))
   84: 	      | DEL_DIR_IS_EMPTY;
   85: 
   86: 	for (j = dirlist->used; j--; ) {
   87: 		struct file_struct *fp = dirlist->files[j];
   88: 
   89: 		if (fp->flags & FLAG_MOUNT_DIR && S_ISDIR(fp->mode)) {
   90: 			if (DEBUG_GTE(DEL, 1)) {
   91: 				rprintf(FINFO,
   92: 				    "mount point, %s, pins parent directory\n",
   93: 				    f_name(fp, NULL));
   94: 			}
   95: 			ret = DR_NOT_EMPTY;
   96: 			continue;
   97: 		}
   98: 
   99: 		strlcpy(p, fp->basename, remainder);
  100: 		if (!(fp->mode & S_IWUSR) && !am_root && fp->flags & FLAG_OWNED_BY_US)
  101: 			do_chmod(fname, fp->mode | S_IWUSR);
  102: 		/* Save stack by recursing to ourself directly. */
  103: 		if (S_ISDIR(fp->mode)) {
  104: 			if (delete_dir_contents(fname, flags | DEL_RECURSE) != DR_SUCCESS)
  105: 				ret = DR_NOT_EMPTY;
  106: 		}
  107: 		if (delete_item(fname, fp->mode, flags) != DR_SUCCESS)
  108: 			ret = DR_NOT_EMPTY;
  109: 	}
  110: 
  111: 	fname[dlen] = '\0';
  112: 
  113:   done:
  114: 	flist_free(dirlist);
  115: 	pop_local_filters(save_filters);
  116: 
  117: 	if (ret == DR_NOT_EMPTY) {
  118: 		rprintf(FINFO, "cannot delete non-empty directory: %s\n",
  119: 			fname);
  120: 	}
  121: 	return ret;
  122: }
  123: 
  124: /* Delete a file or directory.  If DEL_RECURSE is set in the flags, this will
  125:  * delete recursively.
  126:  *
  127:  * Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's
  128:  * a directory! (The buffer is used for recursion, but returned unchanged.)
  129:  */
  130: enum delret delete_item(char *fbuf, uint16 mode, uint16 flags)
  131: {
  132: 	enum delret ret;
  133: 	char *what;
  134: 	int ok;
  135: 
  136: 	if (DEBUG_GTE(DEL, 2)) {
  137: 		rprintf(FINFO, "delete_item(%s) mode=%o flags=%d\n",
  138: 			fbuf, (int)mode, (int)flags);
  139: 	}
  140: 
  141: 	if (flags & DEL_NO_UID_WRITE)
  142: 		do_chmod(fbuf, mode | S_IWUSR);
  143: 
  144: 	if (S_ISDIR(mode) && !(flags & DEL_DIR_IS_EMPTY)) {
  145: 		/* This only happens on the first call to delete_item() since
  146: 		 * delete_dir_contents() always calls us w/DEL_DIR_IS_EMPTY. */
  147: 		ignore_perishable = 1;
  148: 		/* If DEL_RECURSE is not set, this just reports emptiness. */
  149: 		ret = delete_dir_contents(fbuf, flags);
  150: 		ignore_perishable = 0;
  151: 		if (ret == DR_NOT_EMPTY || ret == DR_AT_LIMIT)
  152: 			goto check_ret;
  153: 		/* OK: try to delete the directory. */
  154: 	}
  155: 
  156: 	if (!(flags & DEL_MAKE_ROOM) && max_delete >= 0 && stats.deleted_files >= max_delete) {
  157: 		skipped_deletes++;
  158: 		return DR_AT_LIMIT;
  159: 	}
  160: 
  161: 	if (S_ISDIR(mode)) {
  162: 		what = "rmdir";
  163: 		ok = do_rmdir(fbuf) == 0;
  164: 	} else {
  165: 		if (make_backups > 0 && !(flags & DEL_FOR_BACKUP) && (backup_dir || !is_backup_file(fbuf))) {
  166: 			what = "make_backup";
  167: 			ok = make_backup(fbuf, True);
  168: 			if (ok == 2) {
  169: 				what = "unlink";
  170: 				ok = robust_unlink(fbuf) == 0;
  171: 			}
  172: 		} else {
  173: 			what = "unlink";
  174: 			ok = robust_unlink(fbuf) == 0;
  175: 		}
  176: 	}
  177: 
  178: 	if (ok) {
  179: 		if (!(flags & DEL_MAKE_ROOM)) {
  180: 			log_delete(fbuf, mode);
  181: 			stats.deleted_files++;
  182: 			if (S_ISREG(mode)) {
  183: 				/* Nothing more to count */
  184: 			} else if (S_ISDIR(mode))
  185: 				stats.deleted_dirs++;
  186: #ifdef SUPPORT_LINKS
  187: 			else if (S_ISLNK(mode))
  188: 				stats.deleted_symlinks++;
  189: #endif
  190: 			else if (IS_DEVICE(mode))
  191: 				stats.deleted_symlinks++;
  192: 			else
  193: 				stats.deleted_specials++;
  194: 		}
  195: 		ret = DR_SUCCESS;
  196: 	} else {
  197: 		if (S_ISDIR(mode) && errno == ENOTEMPTY) {
  198: 			rprintf(FINFO, "cannot delete non-empty directory: %s\n",
  199: 				fbuf);
  200: 			ret = DR_NOT_EMPTY;
  201: 		} else if (errno != ENOENT) {
  202: 			rsyserr(FERROR, errno, "delete_file: %s(%s) failed",
  203: 				what, fbuf);
  204: 			ret = DR_FAILURE;
  205: 		} else
  206: 			ret = DR_SUCCESS;
  207: 	}
  208: 
  209:   check_ret:
  210: 	if (ret != DR_SUCCESS && flags & DEL_MAKE_ROOM) {
  211: 		const char *desc;
  212: 		switch (flags & DEL_MAKE_ROOM) {
  213: 		case DEL_FOR_FILE: desc = "regular file"; break;
  214: 		case DEL_FOR_DIR: desc = "directory"; break;
  215: 		case DEL_FOR_SYMLINK: desc = "symlink"; break;
  216: 		case DEL_FOR_DEVICE: desc = "device file"; break;
  217: 		case DEL_FOR_SPECIAL: desc = "special file"; break;
  218: 		default: exit_cleanup(RERR_UNSUPPORTED); /* IMPOSSIBLE */
  219: 		}
  220: 		rprintf(FERROR_XFER, "could not make way for %s %s: %s\n",
  221: 			flags & DEL_FOR_BACKUP ? "backup" : "new",
  222: 			desc, fbuf);
  223: 	}
  224: 	return ret;
  225: }
  226: 
  227: uint16 get_del_for_flag(uint16 mode)
  228: {
  229: 	if (S_ISREG(mode))
  230: 		return DEL_FOR_FILE;
  231: 	if (S_ISDIR(mode))
  232: 		return DEL_FOR_DIR;
  233: 	if (S_ISLNK(mode))
  234: 		return DEL_FOR_SYMLINK;
  235: 	if (IS_DEVICE(mode))
  236: 		return DEL_FOR_DEVICE;
  237: 	if (IS_SPECIAL(mode))
  238: 		return DEL_FOR_SPECIAL;
  239: 	exit_cleanup(RERR_UNSUPPORTED); /* IMPOSSIBLE */
  240: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>