- if ((fd = open(dest, O_WRONLY|O_CREAT, source_stat.st_mode)) < 0 ||
- (dfp = fdopen(fd, "w")) == NULL) {
- if (fd >= 0)
- close(fd);
- perror_msg("unable to open `%s'", dest);
+ // POSIX: if exists and -i, ask (w/o -i assume yes).
+ // Then open w/o EXCL.
+ // If open still fails and -f, try unlink, then try open again.
+ // Result: a mess:
+ // If dest is a softlink, we overwrite softlink's destination!
+ // (or fail, if it points to dir/nonexistent location/etc).
+ // This is strange, but POSIX-correct.
+ // coreutils cp has --remove-destination to override this...
+ dst_fd = open(dest, (flags & FILEUTILS_INTERACTIVE)
+ ? O_WRONLY|O_CREAT|O_TRUNC|O_EXCL
+ : O_WRONLY|O_CREAT|O_TRUNC, source_stat.st_mode);
+ if (dst_fd == -1) {
+ // We would not do POSIX insanity. -i asks,
+ // then _unlinks_ the offender. Presto.
+ // Or else we will end up having 3 open()s!
+ ovr = retry_overwrite(dest, flags);
+ if (ovr <= 0) {
+ close(src_fd);
+ return ovr;
+ }
+ dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, source_stat.st_mode);
+ if (dst_fd == -1) {
+ bb_perror_msg("cannot open '%s'", dest);
+ close(src_fd);