Delete a file or directory. If DEL_RECURSE is set in the flags, this will * delete recursively. * * Note that fbuf must point to a MAXPATHLEN buffer if the mode indicates it's * a directory! (The buffer is used for recursion, but returned unchanged.) */
| 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_at(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_at(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)) |
no test coverage detected