Skip to content

Commit

Permalink
copy_file(): remove incomplete file on error (bug 2890715)
Browse files Browse the repository at this point in the history
The behavior changed, data is first written to a temporary file,
which is unlinked in case of error, then the tempfile is renamed
to the final name.
Size of buffer was increased from 4k to 16k.
  • Loading branch information
Laurent Monin committed Jan 10, 2010
1 parent 8ce20c2 commit 36ee9c9
Showing 1 changed file with 40 additions and 26 deletions.
66 changes: 40 additions & 26 deletions src/ui_fileops.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,52 +520,66 @@ gboolean copy_file(const gchar *s, const gchar *t)
{
FILE *fi = NULL;
FILE *fo = NULL;
gchar *sl, *tl;
gchar buf[4096];
gchar *sl = NULL;
gchar *tl = NULL;
gchar *randname = NULL;
gchar buf[16384];
size_t b;
gint ret = FALSE;
gint fd = -1;

sl = path_from_utf8(s);
tl = path_from_utf8(t);

if (hard_linked(sl, tl))
{
g_free(sl);
g_free(tl);
return TRUE;
ret = TRUE;
goto end;
}

fi = fopen(sl, "rb");
if (fi)
{
fo = fopen(tl, "wb");
if (!fo)
{
fclose(fi);
fi = NULL;
}
}

g_free(sl);
g_free(tl);

if (!fi || !fo) return FALSE;
if (!fi) goto end;

/* First we write to a temporary file, then we rename it on success,
and attributes from original file are copied */
randname = g_strconcat(tl, ".tmp_XXXXXX", NULL);
if (!randname) goto end;

fd = g_mkstemp(randname);
if (fd == -1) goto end;

fo = fdopen(fd, "wb");
if (!fo) {
close(fd);
goto end;
}

while ((b = fread(buf, sizeof(gchar), sizeof(buf), fi)) && b != 0)
{
if (fwrite(buf, sizeof(gchar), b, fo) != b)
{
fclose(fi);
fclose(fo);
return FALSE;
unlink(randname);
goto end;
}
}

fclose(fi);
fclose(fo);
fclose(fi); fi = NULL;
fclose(fo); fo = NULL;

copy_file_attributes(s, t, TRUE, TRUE);
if (rename(randname, tl) < 0) {
unlink(randname);
goto end;
}

return TRUE;
ret = copy_file_attributes(s, t, TRUE, TRUE);

end:
if (fi) fclose(fi);
if (fo) fclose(fo);
if (sl) g_free(sl);
if (tl) g_free(tl);
if (randname) g_free(randname);
return ret;
}

gboolean move_file(const gchar *s, const gchar *t)
Expand Down

0 comments on commit 36ee9c9

Please sign in to comment.