The Samba-Bugzilla – Attachment 2956 Details for
Bug 5051
--copy-dest copies should use a temporary file unless --inplace
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Attempt to implement temporary file usage, etc.
fix-5051.diff (text/plain), 7.72 KB, created by
Matt McCutchen
on 2007-10-28 00:19:02 UTC
(
hide
)
Description:
Attempt to implement temporary file usage, etc.
Filename:
MIME Type:
Creator:
Matt McCutchen
Created:
2007-10-28 00:19:02 UTC
Size:
7.72 KB
patch
obsolete
>Fix https://bugzilla.samba.org/show_bug.cgi?id=5051 > >--- old/generator.c >+++ new/generator.c >@@ -830,6 +830,40 @@ static int find_fuzzy(struct file_struct > return lowest_j; > } > >+/* Do a --copy-dest local copy. */ >+static int do_local_copy(char *fname, struct file_struct *file, char *cmpbuf) >+{ >+ char fnametmpbuf[MAXPATHLEN], *fnametmp; >+ int fd_w; >+ >+ if (inplace) { >+ /* Let copy_file open the destination in place. */ >+ fd_w = -1; >+ fnametmp = fname; >+ } else { >+ fd_w = open_tmpfile(fnametmpbuf, fname, file); >+ if (fd_w < 0) >+ return -1; >+ fnametmp = fnametmpbuf; >+ } >+ cleanup_set(fnametmp, NULL, NULL, -1, -1); >+ if (copy_file(cmpbuf, fnametmp, fd_w, file->mode, 0) < 0) { >+ /* Try to clean up. */ >+ unlink(fnametmp); >+ cleanup_disable(); >+ if (verbose) { >+ rsyserr(FINFO, errno, "copy_file %s => %s", >+ full_fname(cmpbuf), fnametmp); >+ } >+ return -1; >+ } >+ finish_transfer(fname, fnametmp, cmpbuf, >+ partial_dir ? partial_dir_fname(fname) : NULL, >+ file, 1, 0); >+ cleanup_disable(); >+ return 0; >+} >+ > /* This is only called for regular files. We return -2 if we've finished > * handling the file, -1 if no dest-linking occurred, or a non-negative > * value if we found an alternate basis file. */ >@@ -904,14 +938,8 @@ static int try_dests_reg(struct file_str > #ifdef SUPPORT_HARD_LINKS > try_a_copy: /* Copy the file locally. */ > #endif >- if (!dry_run && copy_file(cmpbuf, fname, file->mode, 0) < 0) { >- if (verbose) { >- rsyserr(FINFO, errno, "copy_file %s => %s", >- full_fname(cmpbuf), fname); >- } >+ if (!dry_run && do_local_copy(fname, file, cmpbuf) < 0) > return -1; >- } >- set_file_attrs(fname, file, NULL, cmpbuf, 0); > if (itemizing) > itemize(cmpbuf, file, ndx, 0, sxp, ITEM_LOCAL_CHANGE, 0, NULL); > #ifdef SUPPORT_XATTRS >@@ -1680,7 +1708,7 @@ static void recv_generator(char *fname, > goto cleanup; > if (!(back_file = make_file(fname, NULL, NULL, 0, NO_FILTERS))) > goto pretend_missing; >- if (copy_file(fname, backupptr, back_file->mode, 1) < 0) { >+ if (copy_file(fname, backupptr, -1, back_file->mode, 1) < 0) { > unmake_file(back_file); > back_file = NULL; > goto cleanup; >--- old/receiver.c >+++ new/receiver.c >@@ -123,6 +123,42 @@ int get_tmpname(char *fnametmp, char *fn > return 1; > } > >+/* Opens a temporary file for writing. >+ * Success: Writes name into fnametmp, returns fd. >+ * Failure: Clobbers fnametmp, returns -1. >+ * cleanup_set is the caller's job. */ >+int open_tmpfile(char *fnametmp, char *fname, struct file_struct *file) >+{ >+ int fd; >+ >+ if (!get_tmpname(fnametmp,fname)) >+ return -1; >+ >+ /* we initially set the perms without the >+ * setuid/setgid bits to ensure that there is no race >+ * condition. They are then correctly updated after >+ * the lchown. Thanks to snabb@epipe.fi for pointing >+ * this out. We also set it initially without group >+ * access because of a similar race condition. */ >+ fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS); >+ >+ /* in most cases parent directories will already exist >+ * because their information should have been previously >+ * transferred, but that may not be the case with -R */ >+ if (fd == -1 && relative_paths && errno == ENOENT >+ && create_directory_path(fnametmp) == 0) { >+ /* Get back to name with XXXXXX in it. */ >+ get_tmpname(fnametmp, fname); >+ fd = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS); >+ } >+ if (fd == -1) { >+ rsyserr(FERROR, errno, "mkstemp %s failed", >+ full_fname(fnametmp)); >+ return -1; >+ } >+ >+ return fd; >+} > > static int receive_data(int f_in, char *fname_r, int fd_r, OFF_T size_r, > const char *fname, int fd, OFF_T total_size) >@@ -606,55 +642,22 @@ int recv_files(int f_in, char *local_nam > /* We now check to see if we are writing the file "inplace" */ > if (inplace) { > fd2 = do_open(fname, O_WRONLY|O_CREAT, 0600); >- if (fd2 == -1) { >+ if (fd2 == -1) > rsyserr(FERROR, errno, "open %s failed", > full_fname(fname)); >- discard_receive_data(f_in, F_LENGTH(file)); >- if (fd1 != -1) >- close(fd1); >- if (inc_recurse) >- send_msg_int(MSG_NO_SEND, ndx); >- continue; >- } > } else { >- if (!get_tmpname(fnametmp,fname)) { >- discard_receive_data(f_in, F_LENGTH(file)); >- if (fd1 != -1) >- close(fd1); >- if (inc_recurse) >- send_msg_int(MSG_NO_SEND, ndx); >- continue; >- } >- >- /* we initially set the perms without the >- * setuid/setgid bits to ensure that there is no race >- * condition. They are then correctly updated after >- * the lchown. Thanks to snabb@epipe.fi for pointing >- * this out. We also set it initially without group >- * access because of a similar race condition. */ >- fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS); >- >- /* in most cases parent directories will already exist >- * because their information should have been previously >- * transferred, but that may not be the case with -R */ >- if (fd2 == -1 && relative_paths && errno == ENOENT >- && create_directory_path(fnametmp) == 0) { >- /* Get back to name with XXXXXX in it. */ >- get_tmpname(fnametmp, fname); >- fd2 = do_mkstemp(fnametmp, file->mode & INITACCESSPERMS); >- } >- if (fd2 == -1) { >- rsyserr(FERROR, errno, "mkstemp %s failed", >- full_fname(fnametmp)); >- discard_receive_data(f_in, F_LENGTH(file)); >- if (fd1 != -1) >- close(fd1); >- if (inc_recurse) >- send_msg_int(MSG_NO_SEND, ndx); >- continue; >- } >+ fd2 = open_tmpfile(fnametmp, fname, file); >+ if (fd2 != -1) >+ cleanup_set(fnametmp, partialptr, file, fd1, fd2); >+ } > >- cleanup_set(fnametmp, partialptr, file, fd1, fd2); >+ if (fd2 == -1) { >+ discard_receive_data(f_in, F_LENGTH(file)); >+ if (fd1 != -1) >+ close(fd1); >+ if (inc_recurse) >+ send_msg_int(MSG_NO_SEND, ndx); >+ continue; > } > > /* log the transfer */ >--- old/util.c >+++ new/util.c >@@ -261,14 +261,15 @@ static int safe_read(int desc, char *ptr > return n_chars; > } > >-/** Copy a file. >+/** Copy a file. If ofd == -1, copy_file unlinks and opens the file itself; >+ * otherwise it just writes to and closes the provided file descriptor. > * >- * This is used in conjunction with the --temp-dir, --backup, and >- * --copy-dest options. */ >-int copy_file(const char *source, const char *dest, mode_t mode, int create_bak_dir) >+ * This is used in conjunction with the --temp-dir, --backup, >+ * --copy-dest, and --no-tweak* options. */ >+int copy_file(const char *source, const char *dest, int ofd, >+ mode_t mode, int create_bak_dir) > { > int ifd; >- int ofd; > char buf[1024 * 8]; > int len; /* Number of bytes read into `buf'. */ > >@@ -277,17 +278,19 @@ int copy_file(const char *source, const > return -1; > } > >- if (robust_unlink(dest) && errno != ENOENT) { >- rsyserr(FERROR, errno, "unlink %s", full_fname(dest)); >- return -1; >- } >+ if (ofd == -1) { >+ if (robust_unlink(dest) && errno != ENOENT) { >+ rsyserr(FERROR, errno, "unlink %s", full_fname(dest)); >+ return -1; >+ } > >- if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0 >- && (!create_bak_dir || errno != ENOENT || make_bak_dir(dest) < 0 >- || (ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)) { >- rsyserr(FERROR, errno, "open %s", full_fname(dest)); >- close(ifd); >- return -1; >+ if ((ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0 >+ && (!create_bak_dir || errno != ENOENT || make_bak_dir(dest) < 0 >+ || (ofd = do_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, mode)) < 0)) { >+ rsyserr(FERROR, errno, "open %s", full_fname(dest)); >+ close(ifd); >+ return -1; >+ } > } > > while ((len = safe_read(ifd, buf, sizeof buf)) > 0) { >@@ -407,7 +410,7 @@ int robust_rename(const char *from, cons > return -1; > to = partialptr; > } >- if (copy_file(from, to, mode, 0) != 0) >+ if (copy_file(from, to, -1, mode, 0) != 0) > return -2; > do_unlink(from); > return 1;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 5051
: 2956