Move var declaration for older C compilers.
[rsync.git] / delete.c
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-2009 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 }