Merge branch '4532_copy_move_attrs'

* 4532_copy_move_attrs:
  mceditor: support ext2fs attributes.
  Ticket #4451: preserve ext2fs attributes on copy/move operations.
This commit is contained in:
Andrew Borodin 2024-03-31 18:48:21 +03:00
commit 25f008c0b0
4 changed files with 146 additions and 1 deletions

View File

@ -2164,6 +2164,8 @@ edit_init (WEdit * edit, const WRect * r, const vfs_path_t * filename_vpath, lon
edit->stat1.st_gid = getgid ();
edit->stat1.st_mtime = 0;
edit->attrs_ok = (mc_fgetflags (filename_vpath, &edit->attrs) == 0);
edit->over_col = 0;
edit->bracket = -1;
edit->last_bracket = -1;

View File

@ -239,6 +239,8 @@ edit_save_file (WEdit * edit, const vfs_path_t * filename_vpath)
(void) mc_chown (savename_vpath, edit->stat1.st_uid, edit->stat1.st_gid);
(void) mc_chmod (savename_vpath, edit->stat1.st_mode);
if (edit->attrs_ok)
(void) mc_fsetflags (savename_vpath, edit->attrs);
fd = mc_open (savename_vpath, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, edit->stat1.st_mode);
if (fd == -1)

View File

@ -150,6 +150,9 @@ struct WEdit
unsigned int redo_stack_reset:1; /* If 1, need clear redo stack */
struct stat stat1; /* Result of mc_fstat() on the file */
unsigned long attrs; /* Result of mc_fgetflags() on the file */
gboolean attrs_ok; /* mc_fgetflags() == 0 */
unsigned int skip_detach_prompt:1; /* Do not prompt whether to detach a file anymore */
/* syntax highlighting */

View File

@ -2272,6 +2272,8 @@ copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx,
mode_t src_mode = 0; /* The mode of the source file */
struct stat src_stat, dst_stat;
mc_timesbuf_t times;
unsigned long attrs;
gboolean attrs_ok = ctx->preserve;
gboolean dst_exists = FALSE, appending = FALSE;
off_t file_size = -1;
FileProgressStatus return_status, temp_status;
@ -2336,6 +2338,30 @@ copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx,
goto ret_fast;
}
while (attrs_ok && mc_fgetflags (src_vpath, &attrs) != 0)
{
attrs_ok = FALSE;
/* don't show an error message if attributes aren't supported in this FS */
if (errno == ENOTSUP)
return_status = FILE_CONT;
else if (ctx->skip_all)
return_status = FILE_SKIPALL;
else
{
return_status =
file_error (TRUE, _("Cannot get attributes of source file \"%s\"\n%s"), src_path);
if (return_status == FILE_SKIPALL)
ctx->skip_all = TRUE;
}
if (return_status != FILE_RETRY)
break;
/* yet another attempt */
attrs_ok = TRUE;
}
if (dst_exists)
{
/* Destination already exists */
@ -2379,7 +2405,30 @@ copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx,
{
return_status = make_symlink (ctx, src_vpath, dst_vpath);
if (return_status == FILE_CONT && ctx->preserve)
{
mc_utime (dst_vpath, &times);
while (attrs_ok && mc_fsetflags (dst_vpath, attrs) != 0 && !ctx->skip_all)
{
attrs_ok = FALSE;
/* don't show an error message if attributes aren't supported in this FS */
if (errno == ENOTSUP)
return_status = FILE_CONT;
else if (return_status == FILE_SKIPALL)
ctx->skip_all = TRUE;
else
return_status =
file_error (TRUE, _("Cannot set attributes of target file \"%s\"\n%s"),
dst_path);
if (return_status != FILE_RETRY)
break;
/* yet another attempt */
attrs_ok = TRUE;
}
}
goto ret_fast;
}
@ -2435,6 +2484,31 @@ copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx,
}
}
while (attrs_ok && mc_fsetflags (dst_vpath, attrs) != 0 && !ctx->skip_all)
{
attrs_ok = FALSE;
/* don't show an error message if attributes aren't supported in this FS */
if (errno == ENOTSUP)
break;
temp_status =
file_error (TRUE, _("Cannot set attributes of target file \"%s\"\n%s"),
dst_path);
if (temp_status == FILE_SKIP)
break;
if (temp_status == FILE_SKIPALL)
ctx->skip_all = TRUE;
if (temp_status != FILE_RETRY)
{
return_status = temp_status;
goto ret_fast;
}
/* yet another attempt */
attrs_ok = TRUE;
}
return_status = FILE_CONT;
mc_utime (dst_vpath, &times);
goto ret_fast;
@ -2817,10 +2891,40 @@ copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx,
}
}
/* Always sync timestamps */
if (dst_status == DEST_FULL || dst_status == DEST_SHORT_KEEP)
{
/* Always sync timestamps */
mc_utime (dst_vpath, &times);
while (attrs_ok && mc_fsetflags (dst_vpath, attrs) != 0 && !ctx->skip_all)
{
attrs_ok = FALSE;
/* don't show an error message if attributes aren't supported in this FS */
if (errno == ENOTSUP)
{
return_status = FILE_CONT;
break;
}
temp_status = file_error (TRUE, _("Cannot set attributes for target file \"%s\"\n%s"),
dst_path);
if (temp_status == FILE_RETRY)
{
attrs_ok = TRUE;
continue;
}
if (temp_status == FILE_SKIPALL)
{
ctx->skip_all = TRUE;
return_status = FILE_CONT;
}
if (temp_status == FILE_SKIP)
return_status = FILE_CONT;
break;
}
}
if (return_status == FILE_CONT)
return_status = progress_update_one (tctx, ctx, file_size);
@ -2844,6 +2948,8 @@ copy_dir_dir (file_op_total_context_t * tctx, file_op_context_t * ctx, const cha
{
struct vfs_dirent *next;
struct stat dst_stat, src_stat;
unsigned long attrs;
gboolean attrs_ok = ctx->preserve;
DIR *reading;
FileProgressStatus return_status = FILE_CONT;
struct link *lp;
@ -2871,6 +2977,34 @@ copy_dir_dir (file_op_total_context_t * tctx, file_op_context_t * ctx, const cha
goto ret_fast;
}
while (attrs_ok && mc_fgetflags (src_vpath, &attrs) != 0)
{
attrs_ok = FALSE;
/* don't show an error message if attributes aren't supported in this FS */
if (errno == ENOTSUP)
{
return_status = FILE_CONT;
break;
}
if (ctx->skip_all)
return_status = FILE_SKIPALL;
else
{
return_status =
file_error (TRUE, _("Cannot get attributes of source directory \"%s\"\n%s"), s);
if (return_status == FILE_RETRY)
{
attrs_ok = TRUE;
continue;
}
if (return_status == FILE_SKIPALL)
ctx->skip_all = TRUE;
}
goto ret_fast;
}
if (is_in_linklist (dest_dirs, src_vpath, &src_stat) != NULL)
{
/* Don't copy a directory we created before (we don't want to copy
@ -3097,6 +3231,10 @@ copy_dir_dir (file_op_total_context_t * tctx, file_op_context_t * ctx, const cha
mc_timesbuf_t times;
mc_chmod (dst_vpath, src_stat.st_mode & ctx->umask_kill);
if (attrs_ok)
mc_fsetflags (dst_vpath, attrs);
get_times (&src_stat, &times);
mc_utime (dst_vpath, &times);
}