Ticket #3297: don't lose file in case of preallocate space fail.

Don't remove the destination file if it was retrieved incompletely
but it was already exist and appended during copy/move operation.

Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
This commit is contained in:
Andrew Borodin 2014-11-10 10:32:34 +03:00
parent 63e8eae0b1
commit a3486faac3

View File

@ -1497,7 +1497,6 @@ copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx,
int open_flags;
gboolean is_first_time = TRUE;
vfs_path_t *src_vpath = NULL, *dst_vpath = NULL;
gboolean write_errno_nospace = FALSE;
/* FIXME: We should not be using global variables! */
ctx->do_reget = 0;
@ -1739,28 +1738,39 @@ copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx,
goto ret;
}
while (TRUE)
/* try preallocate space; if fail, try copy anyway */
while (vfs_preallocate (dest_desc, file_size, ctx->do_append != 0 ? sb.st_size : 0) != 0)
{
errno = vfs_preallocate (dest_desc, file_size, (ctx->do_append != 0) ? sb.st_size : 0);
if (errno == 0)
break;
if (ctx->skip_all)
return_status = FILE_SKIPALL;
else
{
return_status =
file_error (_("Cannot preallocate space for target file \"%s\"\n%s"), dst_path);
if (return_status == FILE_RETRY)
continue;
if (return_status == FILE_SKIPALL)
ctx->skip_all = TRUE;
/* cannot allocate, start the file copying anyway */
return_status = FILE_CONT;
break;
}
mc_close (dest_desc);
dest_desc = -1;
mc_unlink (dst_vpath);
dst_status = DEST_NONE;
goto ret;
return_status =
file_error (_("Cannot preallocate space for target file \"%s\"\n%s"), dst_path);
if (return_status == FILE_SKIPALL)
ctx->skip_all = TRUE;
if (ctx->skip_all || return_status == FILE_SKIP)
{
/* skip the space allocation error, start file copying */
return_status = FILE_CONT;
break;
}
if (return_status == FILE_ABORT)
{
mc_close (dest_desc);
dest_desc = -1;
mc_unlink (dst_vpath);
dst_status = DEST_NONE;
goto ret;
}
/* return_status == FILE_RETRY -- try allocate space again */
}
ctx->eta_secs = 0.0;
@ -1822,6 +1832,8 @@ copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx,
/* dst_write */
while ((n_written = mc_write (dest_desc, t, n_read)) < n_read)
{
gboolean write_errno_nospace;
if (n_written > 0)
{
n_read -= n_written;
@ -1851,10 +1863,6 @@ copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx,
}
if (return_status != FILE_RETRY)
goto ret;
/* User pressed "Retry". Will the next mc_write() call be successful?
* Reset error flag to be ready for that. */
write_errno_nospace = FALSE;
}
}
@ -1933,16 +1941,9 @@ copy_file_file (file_op_total_context_t * tctx, file_op_context_t * ctx,
if (dst_status == DEST_SHORT)
{
/* Remove short file */
int result = 0;
/* In case of copy/move to full partition, keep source file
* and remove incomplete destination one */
if (!write_errno_nospace)
result = query_dialog (Q_ ("DialogTitle|Copy"),
_("Incomplete file was retrieved. Keep it?"),
D_ERROR, 2, _("&Delete"), _("&Keep"));
if (result == 0)
/* Query to remove short file */
if (query_dialog (Q_ ("DialogTitle|Copy"), _("Incomplete file was retrieved. Keep it?"),
D_ERROR, 2, _("&Delete"), _("&Keep")) == 0)
mc_unlink (dst_vpath);
}
else if (dst_status == DEST_FULL)