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;