diff --git a/bin/cp/utils.c b/bin/cp/utils.c index ad9695c..96ca12d 100644 --- a/bin/cp/utils.c +++ b/bin/cp/utils.c @@ -117,27 +117,29 @@ copy_file(const FTSENT *entp, int dne) return (1); } } - - if (fflag) { - /* remove existing destination file name, - * create a new file */ - (void)unlink(to.p_path); - if (!lflag) - to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT, - fs->st_mode & ~(S_ISUID | S_ISGID)); - } else { - if (!lflag) - /* overwrite existing destination file name */ - to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0); - } - } else { + if (!lflag) - to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT, - fs->st_mode & ~(S_ISUID | S_ISGID)); + to_fd = open(to.p_path, O_WRONLY | O_TRUNC); + + if ((to_fd == -1 || lflag) && fflag) { + /* Unlink when open() fails, as per POSIX. */ + if (unlink(to.p_path)) { + warn("unlinking %s", to.p_path); + close(from_fd); + return (1); + } + /* Try again with O_CREAT set. */ + dne = 1; + } } - + + if (dne && !lflag) { + to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT, + fs->st_mode & ~(S_ISUID | S_ISGID)); + } + if (to_fd == -1) { - warn("%s", to.p_path); + warn("opening %s", to.p_path); (void)close(from_fd); return (1); }