summaryrefslogtreecommitdiff
blob: d84c3484ceba1d46f1e37e93cfb96f6e4f6659ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
commit a3486faac37680e3bcf7d0b3905f745765a823fd
Author: Andrew Borodin <aborodin@vmail.ru>
Date:   Mon Nov 10 10:32:34 2014 +0300

    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>

diff --git a/src/filemanager/file.c b/src/filemanager/file.c
index 9fbf081..3009ccf 100644
--- a/src/filemanager/file.c
+++ b/src/filemanager/file.c
@@ -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)
+        if (ctx->skip_all)
+        {
+            /* cannot allocate, start the file copying anyway */
+            return_status = FILE_CONT;
             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_SKIPALL)
+            ctx->skip_all = TRUE;
+
+        if (ctx->skip_all || return_status == FILE_SKIP)
         {
-            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;
+            /* skip the space allocation error, start file copying */
+            return_status = FILE_CONT;
+            break;
         }
-        mc_close (dest_desc);
-        dest_desc = -1;
-        mc_unlink (dst_vpath);
-        dst_status = DEST_NONE;
-        goto ret;
+
+        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)