+#include "libbb.h"
+
+// POSIX: if exists and -i, ask (w/o -i assume yes).
+// Then open w/o EXCL (yes, not unlink!).
+// 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...
+//
+// NB: we have special code which still allows for "cp file /dev/node"
+// to work POSIX-ly (the only realistic case where it makes sense)
+
+#define DO_POSIX_CP 0 /* 1 - POSIX behavior, 0 - safe behavior */
+
+// errno must be set to relevant value ("why we cannot create dest?")
+// for POSIX mode to give reasonable error message
+static int ask_and_unlink(const char *dest, int flags)
+{
+ int e = errno;
+#if DO_POSIX_CP
+ if (!(flags & (FILEUTILS_FORCE|FILEUTILS_INTERACTIVE))) {
+ // Either it exists, or the *path* doesnt exist
+ bb_perror_msg("cannot create '%s'", dest);
+ return -1;
+ }
+#endif
+ // If !DO_POSIX_CP, act as if -f is always in effect - we don't want
+ // "cannot create" msg, we want unlink to be done (silently unless -i).
+
+ // TODO: maybe we should do it only if ctty is present?
+ if (flags & FILEUTILS_INTERACTIVE) {
+ // We would not do POSIX insanity. -i asks,
+ // then _unlinks_ the offender. Presto.
+ // (No "opening without O_EXCL", no "unlink only if -f")
+ // Or else we will end up having 3 open()s!
+ fprintf(stderr, "%s: overwrite '%s'? ", applet_name, dest);
+ if (!bb_ask_confirmation())
+ return 0; // not allowed to overwrite
+ }
+ if (unlink(dest) < 0) {
+#if ENABLE_FEATURE_VERBOSE_CP_MESSAGE
+ if (e == errno && e == ENOENT) {
+ /* e == ENOTDIR is similar: path has non-dir component,
+ * but in this case we don't even reach copy_file() */
+ bb_error_msg("cannot create '%s': Path does not exist", dest);
+ return -1; // error
+ }
+#endif
+ errno = e;
+ bb_perror_msg("cannot create '%s'", dest);
+ return -1; // error
+ }
+ return 1; // ok (to try again)
+}