Mercurial > geeqie
comparison src/ui_fileops.c @ 1788:6a88c55c6f68
copy_file(): remove incomplete file on error (bug 2890715)
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.
| author | zas_ |
|---|---|
| date | Sun, 10 Jan 2010 14:23:29 +0000 |
| parents | 192d4752fd06 |
| children | 956aab097ea7 |
comparison
equal
deleted
inserted
replaced
| 1787:886746a02b5e | 1788:6a88c55c6f68 |
|---|---|
| 518 | 518 |
| 519 gboolean copy_file(const gchar *s, const gchar *t) | 519 gboolean copy_file(const gchar *s, const gchar *t) |
| 520 { | 520 { |
| 521 FILE *fi = NULL; | 521 FILE *fi = NULL; |
| 522 FILE *fo = NULL; | 522 FILE *fo = NULL; |
| 523 gchar *sl, *tl; | 523 gchar *sl = NULL; |
| 524 gchar buf[4096]; | 524 gchar *tl = NULL; |
| 525 gchar *randname = NULL; | |
| 526 gchar buf[16384]; | |
| 525 size_t b; | 527 size_t b; |
| 528 gint ret = FALSE; | |
| 529 gint fd = -1; | |
| 526 | 530 |
| 527 sl = path_from_utf8(s); | 531 sl = path_from_utf8(s); |
| 528 tl = path_from_utf8(t); | 532 tl = path_from_utf8(t); |
| 529 | 533 |
| 530 if (hard_linked(sl, tl)) | 534 if (hard_linked(sl, tl)) |
| 531 { | 535 { |
| 532 g_free(sl); | 536 ret = TRUE; |
| 533 g_free(tl); | 537 goto end; |
| 534 return TRUE; | |
| 535 } | 538 } |
| 536 | 539 |
| 537 fi = fopen(sl, "rb"); | 540 fi = fopen(sl, "rb"); |
| 538 if (fi) | 541 if (!fi) goto end; |
| 539 { | 542 |
| 540 fo = fopen(tl, "wb"); | 543 /* First we write to a temporary file, then we rename it on success, |
| 541 if (!fo) | 544 and attributes from original file are copied */ |
| 542 { | 545 randname = g_strconcat(tl, ".tmp_XXXXXX", NULL); |
| 543 fclose(fi); | 546 if (!randname) goto end; |
| 544 fi = NULL; | 547 |
| 545 } | 548 fd = g_mkstemp(randname); |
| 546 } | 549 if (fd == -1) goto end; |
| 547 | 550 |
| 548 g_free(sl); | 551 fo = fdopen(fd, "wb"); |
| 549 g_free(tl); | 552 if (!fo) { |
| 550 | 553 close(fd); |
| 551 if (!fi || !fo) return FALSE; | 554 goto end; |
| 555 } | |
| 552 | 556 |
| 553 while ((b = fread(buf, sizeof(gchar), sizeof(buf), fi)) && b != 0) | 557 while ((b = fread(buf, sizeof(gchar), sizeof(buf), fi)) && b != 0) |
| 554 { | 558 { |
| 555 if (fwrite(buf, sizeof(gchar), b, fo) != b) | 559 if (fwrite(buf, sizeof(gchar), b, fo) != b) |
| 556 { | 560 { |
| 557 fclose(fi); | 561 unlink(randname); |
| 558 fclose(fo); | 562 goto end; |
| 559 return FALSE; | |
| 560 } | 563 } |
| 561 } | 564 } |
| 562 | 565 |
| 563 fclose(fi); | 566 fclose(fi); fi = NULL; |
| 564 fclose(fo); | 567 fclose(fo); fo = NULL; |
| 565 | 568 |
| 566 copy_file_attributes(s, t, TRUE, TRUE); | 569 if (rename(randname, tl) < 0) { |
| 567 | 570 unlink(randname); |
| 568 return TRUE; | 571 goto end; |
| 572 } | |
| 573 | |
| 574 ret = copy_file_attributes(s, t, TRUE, TRUE); | |
| 575 | |
| 576 end: | |
| 577 if (fi) fclose(fi); | |
| 578 if (fo) fclose(fo); | |
| 579 if (sl) g_free(sl); | |
| 580 if (tl) g_free(tl); | |
| 581 if (randname) g_free(randname); | |
| 582 return ret; | |
| 569 } | 583 } |
| 570 | 584 |
| 571 gboolean move_file(const gchar *s, const gchar *t) | 585 gboolean move_file(const gchar *s, const gchar *t) |
| 572 { | 586 { |
| 573 gchar *sl, *tl; | 587 gchar *sl, *tl; |
