mirror of https://github.com/MidnightCommander/mc
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:
commit
25f008c0b0
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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, ×);
|
||||
|
||||
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, ×);
|
||||
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, ×);
|
||||
|
||||
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, ×);
|
||||
mc_utime (dst_vpath, ×);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue