summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2008-06-21 17:47:56 +0000
committerkientzle <kientzle@FreeBSD.org>2008-06-21 17:47:56 +0000
commitc0709d3e410563b2a2e5a24d2d62213ae61db682 (patch)
tree9968edc22732384ed881ec64c5fb63ffcae7b263
parentd3bd62e8051581bfc33d309594ddb5c7cf8e2c79 (diff)
downloadFreeBSD-src-c0709d3e410563b2a2e5a24d2d62213ae61db682.zip
FreeBSD-src-c0709d3e410563b2a2e5a24d2d62213ae61db682.tar.gz
If we're using -l and can't hardlink the file because of a cross-device
link, just ignore the -l option and copy the file instead. In particular, this should fix the COPYTREE_* macros used in the ports infrastructure which use -l to preserve space but often get used for cross-device copies.
-rw-r--r--usr.bin/cpio/cpio.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/usr.bin/cpio/cpio.c b/usr.bin/cpio/cpio.c
index 715fb95..e6904a5 100644
--- a/usr.bin/cpio/cpio.c
+++ b/usr.bin/cpio/cpio.c
@@ -537,14 +537,28 @@ entry_to_archive(struct cpio *cpio, struct archive_entry *entry)
* Obviously, this only gets invoked in pass mode.
*/
if (cpio->option_link) {
- /* Note: link(2) doesn't create parent directories. */
- archive_entry_set_hardlink(entry, srcpath);
- r = archive_write_header(cpio->archive, entry);
+ struct archive_entry *t;
+ /* Save the original entry in case we need it later. */
+ t = archive_entry_clone(entry);
+ if (t == NULL)
+ cpio_errc(1, ENOMEM, "Can't create link");
+ /* Note: link(2) doesn't create parent directories,
+ * so we use archive_write_header() instead. */
+ archive_entry_set_hardlink(t, srcpath);
+ r = archive_write_header(cpio->archive, t);
+ archive_entry_free(t);
if (r != ARCHIVE_OK)
cpio_warnc(archive_errno(cpio->archive),
archive_error_string(cpio->archive));
if (r == ARCHIVE_FATAL)
exit(1);
+#ifdef EXDEV
+ if (r != ARCHIVE_OK && archive_errno(cpio->archive) == EXDEV) {
+ /* Cross-device link: Just fall through and use
+ * the original entry to copy the file over. */
+ cpio_warnc(0, "Copying file instead");
+ } else
+#endif
return (0);
}
OpenPOWER on IntegriCloud