Skip to content

Commit 3e940ae

Browse files
committed
Ticket #4720: delete resource forks on macOS last to avoid recursive delete failures
Signed-off-by: Yury V. Zaytsev <yury@shurup.com>
1 parent f03e97f commit 3e940ae

2 files changed

Lines changed: 27 additions & 4 deletions

File tree

lib/fs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@
108108
#define DIR_IS_DOT(x) ((x)[0] == '.' && (x)[1] == '\0')
109109
#define DIR_IS_DOTDOT(x) ((x)[0] == '.' && (x)[1] == '.' && (x)[2] == '\0')
110110

111+
/* On macOS, if a file system doesn't support resource forks, metadata is automatically stored in
112+
* shadow files beginning with `._`. They are automatically managed by the OS and will reappear if
113+
* deleted. */
114+
#define FILE_IS_RESOURCE_FORK(x) ((x)[0] == '.' && (x)[1] == '_' && (x)[2] != '\0')
115+
111116
/*** enums ***************************************************************************************/
112117

113118
/*** structures declarations (and typedefs of structures)*****************************************/

src/filemanager/file.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,9 +1436,14 @@ try_erase_dir (file_op_context_t *ctx, const vfs_path_t *vpath)
14361436
abort -> cancel stack
14371437
ignore -> warn every level, gets default
14381438
ignore_all -> remove as much as possible
1439+
1440+
This function should either be called with delete_resource_forks = TRUE always, or called twice,
1441+
first with FALSE and then with TRUE to make sure that no errors pop up due to resource forks being
1442+
deleted on macOS and then being re-created on the fly by the OS.
14391443
*/
14401444
static FileProgressStatus
1441-
recursive_erase (file_op_context_t *ctx, const vfs_path_t *vpath)
1445+
recursive_erase (file_op_context_t *ctx, const vfs_path_t *vpath,
1446+
const gboolean delete_resource_forks)
14421447
{
14431448
struct vfs_dirent *next;
14441449
DIR *reading;
@@ -1464,9 +1469,18 @@ recursive_erase (file_op_context_t *ctx, const vfs_path_t *vpath)
14641469
return FILE_RETRY;
14651470
}
14661471
if (S_ISDIR (buf.st_mode))
1467-
return_status = recursive_erase (ctx, tmp_vpath);
1472+
{
1473+
return_status = recursive_erase (ctx, tmp_vpath, FALSE);
1474+
if (return_status != FILE_ABORT)
1475+
return_status = recursive_erase (ctx, tmp_vpath, TRUE);
1476+
}
14681477
else
1469-
return_status = erase_file (ctx, tmp_vpath);
1478+
{
1479+
if (delete_resource_forks || !FILE_IS_RESOURCE_FORK (next->d_name))
1480+
return_status = erase_file (ctx, tmp_vpath);
1481+
else
1482+
return_status = FILE_SKIP;
1483+
}
14701484
vfs_path_free (tmp_vpath, TRUE);
14711485
}
14721486
mc_closedir (reading);
@@ -3390,7 +3404,11 @@ erase_dir (file_op_context_t *ctx, const vfs_path_t *vpath)
33903404
// not empty
33913405
error = query_recursive (ctx, vfs_path_as_str (vpath));
33923406
if (error == FILE_CONT)
3393-
error = recursive_erase (ctx, vpath);
3407+
{
3408+
error = recursive_erase (ctx, vpath, FALSE);
3409+
if (error != FILE_ABORT)
3410+
error = recursive_erase (ctx, vpath, TRUE);
3411+
}
33943412
return error;
33953413
}
33963414

0 commit comments

Comments
 (0)