From: Enrico Scholz Date: Sun, 27 Jun 2004 13:04:47 +0000 (+0000) Subject: Unify_unify(): made it work also when destination file does not exist (needed for... X-Git-Tag: IPSENTINEL_VERSION_0_11~49 X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cce0d3d757dba4c849b7b7e907e3e2cf26f8b76b;p=util-vserver.git Unify_unify(): made it work also when destination file does not exist (needed for vcopy) git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@1596 94cd875c-1c1d-0410-91d2-eb244daf1a30 --- diff --git a/util-vserver/lib_internal/unify-unify.c b/util-vserver/lib_internal/unify-unify.c index a3d6a18..8c69cce 100644 --- a/util-vserver/lib_internal/unify-unify.c +++ b/util-vserver/lib_internal/unify-unify.c @@ -37,6 +37,7 @@ Unify_unify(char const *src, struct stat const UNUSED *src_stat, char tmpfile[l + sizeof(";XXXXXX")]; int fd; bool res = false; + struct stat st; // at first, set the ILI flags on 'src' if (vc_set_iattr(src, @@ -45,33 +46,39 @@ Unify_unify(char const *src, struct stat const UNUSED *src_stat, VC_IATTR_IUNLINK|VC_IATTR_IMMUTABLE)==-1) return false; - // now, create a temporary filename - memcpy(tmpfile, dst, l); - memcpy(tmpfile+l, ";XXXXXX", 8); - fd = mkstemp(tmpfile); - close(fd); - - if (fd==-1) { - perror("mkstemp()"); - return false; - } + // check if 'dst' already exists + if (lstat(dst, &st)==0) { + // now, create a temporary filename + memcpy(tmpfile, dst, l); + memcpy(tmpfile+l, ";XXXXXX", 8); + fd = mkstemp(tmpfile); + close(fd); + + if (fd==-1) { + perror("mkstemp()"); + return false; + } - // and rename the old file to this name + // and rename the old file to this name - // NOTE: this rename() is race-free; when an attacker makes 'tmpfile' a - // directory, the operation would fail; when making it a symlink to a file - // or directory, the symlink but not the file/directory would be overridden - if (rename(dst, tmpfile)==-1) { - perror("rename()"); - goto err; + // NOTE: this rename() is race-free; when an attacker makes 'tmpfile' a + // directory, the operation would fail; when making it a symlink to a file + // or directory, the symlink but not the file/directory would be overridden + if (rename(dst, tmpfile)==-1) { + perror("rename()"); + goto err; + } } + else + tmpfile[0] = '\0'; // now, link the src-file to dst if (link(src, dst)==-1) { perror("link()"); unlink(dst); - if (rename(tmpfile, dst)==-1) { + if (tmpfile[0]!='\0' && + rename(tmpfile, dst)==-1) { perror("FATAL error in rename()"); _exit(1); } @@ -81,7 +88,8 @@ Unify_unify(char const *src, struct stat const UNUSED *src_stat, res = true; err: - unlink(tmpfile); + if (tmpfile[0]!='\0') + unlink(tmpfile); return res; }