aboutsummaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorTim Kientzle <kientzle@FreeBSD.org>2008-06-21 17:47:56 +0000
committerTim Kientzle <kientzle@FreeBSD.org>2008-06-21 17:47:56 +0000
commit1aaade6e93d1ecb73c2aa1843ce18087a6fbf5a9 (patch)
tree9968edc22732384ed881ec64c5fb63ffcae7b263 /usr.bin
parentb46d3e21bb870718de398396a5344746aa08a2ef (diff)
Notes
Diffstat (limited to 'usr.bin')
-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 715fb953db93..e6904a5630f9 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);
}