rsync-2.6.1 close() fixes

Sami Farin safari-rsync at safari.iki.fi
Tue Apr 27 18:24:32 GMT 2004


hi.

return value of close() (receiver.c) is ignored.

when running out of quota on NFS (for example),
this can happen (without the patch):
output file(s) is/are truncated to 0 bytes and rsync reports success.

with the fix, this happens:
close "/home/luser/.test.mp3.PwaG50": Disc quota exceeded
rsync error: error in file IO (code 11) at receiver.c(464)
...
...and additionally, test.mp3 is not zapped to 0 bytes.

to be REALLY sure, also fsync() should be used, but that's really
bad for performance if you are transferring _many_ files.
-f and --fsync options added to rsync for the paranoids.


-- 

-------------- next part --------------
--- rsync-2.6.1/receiver.c.bak	2004-03-23 18:50:40.000000000 +0200
+++ rsync-2.6.1/receiver.c	2004-04-27 19:11:46.000000000 +0300
@@ -45,6 +45,7 @@ extern int cleanup_got_literal;
 extern int module_id;
 extern int ignore_errors;
 extern int orig_umask;
+extern int do_fsync;
 
 static void delete_one(char *fn, int is_dir)
 {
@@ -268,6 +269,12 @@ static int receive_data(int f_in,struct 
 		exit_cleanup(RERR_FILEIO);
 	}
 
+	if (do_fsync && (fd != -1) && (fsync(fd) != 0)) {
+		rprintf(FERROR, "fsync failed on %s: %s\n",
+			full_fname(fname), strerror(errno));
+		exit_cleanup(RERR_FILEIO);
+	}
+
 	sum_end(file_sum1);
 
 	read_buf(f_in,file_sum2,MD4_SUM_LENGTH);
@@ -458,7 +465,11 @@ int recv_files(int f_in,struct file_list
 		if (fd1 != -1) {
 			close(fd1);
 		}
-		close(fd2);
+		if (close(fd2) != 0) {
+			rprintf(FERROR, "close failed on %s: %s\n",
+				full_fname(fnametmp), strerror(errno));
+			exit_cleanup(RERR_FILEIO);
+		}
 
 		if (verbose > 2)
 			rprintf(FINFO,"renaming %s to %s\n",fnametmp,fname);
--- rsync-2.6.1/options.c.bak	2004-04-17 20:07:23.000000000 +0300
+++ rsync-2.6.1/options.c	2004-04-27 19:28:10.000000000 +0300
@@ -37,6 +37,7 @@ int make_backups = 0;
  **/
 int whole_file = -1;
 
+int do_fsync = 0;
 int archive_mode = 0;
 int copy_links = 0;
 int preserve_links = 0;
@@ -230,6 +231,7 @@ void usage(enum logcode F)
   rprintf(F," -b, --backup                make backups (see --suffix & --backup-dir)\n");
   rprintf(F,"     --backup-dir            make backups into this directory\n");
   rprintf(F,"     --suffix=SUFFIX         backup suffix (default %s w/o --backup-dir)\n",BACKUP_SUFFIX);
+  rprintf(F," -f, --fsync                 fsync every written file\n");
   rprintf(F," -u, --update                update only (don't overwrite newer files)\n");
   rprintf(F," -l, --links                 copy symlinks as symlinks\n");
   rprintf(F," -L, --copy-links            copy the referent of all symlinks\n");
@@ -332,6 +334,7 @@ static struct poptOption long_options[] 
   {"safe-links",       0,  POPT_ARG_NONE,   &safe_symlinks, 0, 0, 0 },
   {"help",            'h', POPT_ARG_NONE,   0,              'h', 0, 0 },
   {"backup",          'b', POPT_ARG_NONE,   &make_backups, 0, 0, 0 },
+  {"fsync",           'f', POPT_ARG_NONE,   &do_fsync, 0, 0, 0 },
   {"dry-run",         'n', POPT_ARG_NONE,   &dry_run, 0, 0, 0 },
   {"sparse",          'S', POPT_ARG_NONE,   &sparse_files, 0, 0, 0 },
   {"cvs-exclude",     'C', POPT_ARG_NONE,   &cvs_exclude, 0, 0, 0 },
@@ -798,6 +801,8 @@ void server_options(char **args,int *arg
 	/* the -q option is intentionally left out */
 	if (make_backups)
 		argstr[x++] = 'b';
+	if (do_fsync)
+		argstr[x++] = 'f';
 	if (update_only)
 		argstr[x++] = 'u';
 	if (dry_run)
--- rsync-2.6.1/util.c.bak	2004-04-23 01:17:15.000000000 +0300
+++ rsync-2.6.1/util.c	2004-04-27 19:15:29.000000000 +0300
@@ -29,6 +29,7 @@
 
 extern int verbose;
 extern struct exclude_list_struct server_exclude_list;
+extern int do_fsync;
 
 int sanitize_paths = 0;
 
@@ -281,8 +282,22 @@ int copy_file(char *source, char *dest, 
 		}
 	}
 
-	close(ifd);
-	close(ofd);
+	if (close(ifd) != 0) {
+		rprintf(FINFO, "close failed on %s: %s\n",
+			source, strerror(errno));
+	}
+
+	if (do_fsync && (fsync(ofd) != 0)) {
+		rprintf(FERROR, "fsync failed on %s: %s\n",
+			dest, strerror(errno));
+		return -1;
+	}
+
+	if (close(ofd) != 0) {
+		rprintf(FERROR, "close failed on %s: %s\n",
+			dest, strerror(errno));
+		return -1;
+	}
 
 	if (len < 0) {
 		rprintf(FERROR,"read %s: %s\n",


More information about the rsync mailing list