From a009062df166f02f666e8cea17f232b5234e6d79 Mon Sep 17 00:00:00 2001 From: "Yury V. Zaytsev" Date: Mon, 9 Jun 2025 07:33:30 +0200 Subject: [PATCH 1/6] Ticket #4720: delete resource forks on macOS last to avoid recursive delete failures Signed-off-by: Yury V. Zaytsev --- lib/fs.h | 5 +++++ src/filemanager/file.c | 26 ++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/lib/fs.h b/lib/fs.h index 8c5d26f7f..6f5da5d73 100644 --- a/lib/fs.h +++ b/lib/fs.h @@ -108,6 +108,11 @@ #define DIR_IS_DOT(x) ((x)[0] == '.' && (x)[1] == '\0') #define DIR_IS_DOTDOT(x) ((x)[0] == '.' && (x)[1] == '.' && (x)[2] == '\0') +/* On macOS, if a file system doesn't support metadata, it is automatically stored in shadow files + * called resource forks. The names of these files begin with `._`. They are managed automatically + * by the OS. */ +#define FILE_IS_RESOURCE_FORK(x) ((x)[0] == '.' && (x)[1] == '_' && (x)[2] != '\0') + /*** enums ***************************************************************************************/ /*** structures declarations (and typedefs of structures)*****************************************/ diff --git a/src/filemanager/file.c b/src/filemanager/file.c index 54ece4899..cf92125a9 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -1439,9 +1439,14 @@ try_erase_dir (file_op_context_t *ctx, const vfs_path_t *vpath) abort -> cancel stack ignore -> warn every level, gets default ignore_all -> remove as much as possible + + This function should either be called with delete_resource_forks = TRUE always, or called twice, + first with FALSE and then with TRUE to make sure that no errors pop up due to resource forks being + deleted on macOS and then being re-created on the fly by the OS. */ static FileProgressStatus -recursive_erase (file_op_context_t *ctx, const vfs_path_t *vpath) +recursive_erase (file_op_context_t *ctx, const vfs_path_t *vpath, + const gboolean delete_resource_forks) { struct vfs_dirent *next; DIR *reading; @@ -1467,9 +1472,18 @@ recursive_erase (file_op_context_t *ctx, const vfs_path_t *vpath) return FILE_RETRY; } if (S_ISDIR (buf.st_mode)) - return_status = recursive_erase (ctx, tmp_vpath); + { + return_status = recursive_erase (ctx, tmp_vpath, FALSE); + if (return_status != FILE_ABORT) + return_status = recursive_erase (ctx, tmp_vpath, TRUE); + } else - return_status = erase_file (ctx, tmp_vpath); + { + if (!FILE_IS_RESOURCE_FORK (next->d_name) || delete_resource_forks) + return_status = erase_file (ctx, tmp_vpath); + else + return_status = FILE_SKIP; + } vfs_path_free (tmp_vpath, TRUE); } mc_closedir (reading); @@ -3351,7 +3365,11 @@ erase_dir (file_op_context_t *ctx, const vfs_path_t *vpath) // not empty error = query_recursive (ctx, vfs_path_as_str (vpath)); if (error == FILE_CONT) - error = recursive_erase (ctx, vpath); + { + error = recursive_erase (ctx, vpath, FALSE); + if (error != FILE_ABORT) + error = recursive_erase (ctx, vpath, TRUE); + } return error; } From 6d1544c294ad28f1184ba04ed3db679a715b2a3e Mon Sep 17 00:00:00 2001 From: "Yury V. Zaytsev" Date: Mon, 9 Jun 2025 10:06:54 +0200 Subject: [PATCH 2/6] fixup! Ticket #4720: delete resource forks on macOS last to avoid recursive delete failures Signed-off-by: Yury V. Zaytsev --- src/filemanager/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/filemanager/file.c b/src/filemanager/file.c index cf92125a9..7c075d6a9 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -1479,7 +1479,7 @@ recursive_erase (file_op_context_t *ctx, const vfs_path_t *vpath, } else { - if (!FILE_IS_RESOURCE_FORK (next->d_name) || delete_resource_forks) + if (delete_resource_forks || !FILE_IS_RESOURCE_FORK (next->d_name)) return_status = erase_file (ctx, tmp_vpath); else return_status = FILE_SKIP; From e563773fc2f52c80073821aa402f4e34f1042dae Mon Sep 17 00:00:00 2001 From: "Yury V. Zaytsev" Date: Mon, 9 Jun 2025 10:10:12 +0200 Subject: [PATCH 3/6] fixup! fixup! Ticket #4720: delete resource forks on macOS last to avoid recursive delete failures Signed-off-by: Yury V. Zaytsev --- lib/fs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/fs.h b/lib/fs.h index 6f5da5d73..d8490aa6a 100644 --- a/lib/fs.h +++ b/lib/fs.h @@ -108,9 +108,9 @@ #define DIR_IS_DOT(x) ((x)[0] == '.' && (x)[1] == '\0') #define DIR_IS_DOTDOT(x) ((x)[0] == '.' && (x)[1] == '.' && (x)[2] == '\0') -/* On macOS, if a file system doesn't support metadata, it is automatically stored in shadow files - * called resource forks. The names of these files begin with `._`. They are managed automatically - * by the OS. */ +/* On macOS, if a file system doesn't support resource forks, metadata is automatically stored in + * shadow files beginning with `._`. They are automatically managed by the OS and will reappear if + * deleted. */ #define FILE_IS_RESOURCE_FORK(x) ((x)[0] == '.' && (x)[1] == '_' && (x)[2] != '\0') /*** enums ***************************************************************************************/ From e7aa5ecb861f92da7adb594033e4b231bac6f622 Mon Sep 17 00:00:00 2001 From: "Yury V. Zaytsev" Date: Tue, 10 Jun 2025 07:34:58 +0200 Subject: [PATCH 4/6] fixup! fixup! fixup! Ticket #4720: delete resource forks on macOS last to avoid recursive delete failures Signed-off-by: Yury V. Zaytsev --- src/filemanager/file.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/filemanager/file.c b/src/filemanager/file.c index 7c075d6a9..2b903c513 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -1471,6 +1471,7 @@ recursive_erase (file_op_context_t *ctx, const vfs_path_t *vpath, vfs_path_free (tmp_vpath, TRUE); return FILE_RETRY; } +#ifdef __APPLE__ if (S_ISDIR (buf.st_mode)) { return_status = recursive_erase (ctx, tmp_vpath, FALSE); @@ -1479,11 +1480,17 @@ recursive_erase (file_op_context_t *ctx, const vfs_path_t *vpath, } else { - if (delete_resource_forks || !FILE_IS_RESOURCE_FORK (next->d_name)) - return_status = erase_file (ctx, tmp_vpath); - else + if (!delete_resource_forks && FILE_IS_RESOURCE_FORK (next->d_name)) return_status = FILE_SKIP; + else + return_status = erase_file (ctx, tmp_vpath); } +#else + if (S_ISDIR (buf.st_mode)) + return_status = recursive_erase (ctx, tmp_vpath, TRUE); + else + return_status = erase_file (ctx, tmp_vpath); +#endif vfs_path_free (tmp_vpath, TRUE); } mc_closedir (reading); @@ -3366,9 +3373,13 @@ erase_dir (file_op_context_t *ctx, const vfs_path_t *vpath) error = query_recursive (ctx, vfs_path_as_str (vpath)); if (error == FILE_CONT) { +#ifdef __APPLE__ error = recursive_erase (ctx, vpath, FALSE); if (error != FILE_ABORT) error = recursive_erase (ctx, vpath, TRUE); +#else + error = recursive_erase (ctx, vpath, TRUE); +#endif } return error; } From f39514dfb98eb9afe31afc7936e2a3c7dd04fb4e Mon Sep 17 00:00:00 2001 From: "Yury V. Zaytsev" Date: Tue, 10 Jun 2025 07:39:53 +0200 Subject: [PATCH 5/6] fixup! fixup! fixup! fixup! Ticket #4720: delete resource forks on macOS last to avoid recursive delete failures Signed-off-by: Yury V. Zaytsev --- src/filemanager/file.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/filemanager/file.c b/src/filemanager/file.c index 2b903c513..21dcf5c1f 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -1446,7 +1446,10 @@ try_erase_dir (file_op_context_t *ctx, const vfs_path_t *vpath) */ static FileProgressStatus recursive_erase (file_op_context_t *ctx, const vfs_path_t *vpath, - const gboolean delete_resource_forks) +#ifdef __APPLE__ + const gboolean delete_resource_forks +#endif +) { struct vfs_dirent *next; DIR *reading; @@ -1487,7 +1490,7 @@ recursive_erase (file_op_context_t *ctx, const vfs_path_t *vpath, } #else if (S_ISDIR (buf.st_mode)) - return_status = recursive_erase (ctx, tmp_vpath, TRUE); + return_status = recursive_erase (ctx, tmp_vpath); else return_status = erase_file (ctx, tmp_vpath); #endif @@ -3378,7 +3381,7 @@ erase_dir (file_op_context_t *ctx, const vfs_path_t *vpath) if (error != FILE_ABORT) error = recursive_erase (ctx, vpath, TRUE); #else - error = recursive_erase (ctx, vpath, TRUE); + error = recursive_erase (ctx, vpath); #endif } return error; From b2363ba90cc18ecf64fbe49021a63a84c5437031 Mon Sep 17 00:00:00 2001 From: "Yury V. Zaytsev" Date: Tue, 10 Jun 2025 07:41:42 +0200 Subject: [PATCH 6/6] fixup! fixup! fixup! fixup! fixup! Ticket #4720: delete resource forks on macOS last to avoid recursive delete failures Signed-off-by: Yury V. Zaytsev --- src/filemanager/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/filemanager/file.c b/src/filemanager/file.c index 21dcf5c1f..fc86be5b2 100644 --- a/src/filemanager/file.c +++ b/src/filemanager/file.c @@ -1445,8 +1445,9 @@ try_erase_dir (file_op_context_t *ctx, const vfs_path_t *vpath) deleted on macOS and then being re-created on the fly by the OS. */ static FileProgressStatus -recursive_erase (file_op_context_t *ctx, const vfs_path_t *vpath, +recursive_erase (file_op_context_t *ctx, const vfs_path_t *vpath #ifdef __APPLE__ + , const gboolean delete_resource_forks #endif )