summaryrefslogtreecommitdiff
path: root/src/copy.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1998-07-03 20:32:37 +0000
committerJim Meyering <jim@meyering.net>1998-07-03 20:32:37 +0000
commitdef9c2bf0b13346d3f316d0e73f3ce4c62262c9d (patch)
tree37d4de6278b792208be78bbe3d2a0863b74c9c34 /src/copy.c
parent6191d1839ae99ad917f6584739c9543cb1de2ff7 (diff)
downloadcoreutils-def9c2bf0b13346d3f316d0e73f3ce4c62262c9d.tar.xz
(copy_internal): Try harder identifying a relative
symbolic link in the current directory. From Andreas Schwab.
Diffstat (limited to 'src/copy.c')
-rw-r--r--src/copy.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/src/copy.c b/src/copy.c
index 6c563b843..e3aa5ae85 100644
--- a/src/copy.c
+++ b/src/copy.c
@@ -51,6 +51,7 @@ struct dir_list
int full_write ();
int euidaccess ();
int yesno ();
+char *dirname ();
static int copy_internal PARAMS ((const char *src_path, const char *dst_path,
int new_dst, dev_t device,
@@ -662,25 +663,40 @@ copy_internal (const char *src_path, const char *dst_path,
#ifdef S_ISLNK
else if (x->symbolic_link)
{
- if (*src_path == '/'
- || (!strncmp (dst_path, "./", 2) && strchr (dst_path + 2, '/') == 0)
- || strchr (dst_path, '/') == 0)
+ if (*src_path != '/')
{
- if (symlink (src_path, dst_path))
+ /* Check that DST_PATH denotes a file in the current directory. */
+ struct stat dot_sb;
+ struct stat dst_parent_sb;
+ char *dst_parent;
+ int not_current_dir;
+
+ dst_parent = dirname (dst_path);
+ if (dst_parent == NULL)
+ error (1, 0, _("virtual memory exhausted"));
+
+ not_current_dir = (!STREQ (".", dst_parent)
+ && stat (".", &dot_sb) == 0
+ && stat (dst_parent, &dst_parent_sb) == 0
+ && (dot_sb.st_dev != dst_parent_sb.st_dev
+ || dot_sb.st_ino != dst_parent_sb.st_ino));
+ free (dst_parent);
+
+ if (not_current_dir)
{
- error (0, errno, "%s", dst_path);
+ error (0, 0,
+ _("%s: can make relative symbolic links only in current directory"),
+ dst_path);
goto un_backup;
}
-
- return 0;
}
- else
+ if (symlink (src_path, dst_path))
{
- error (0, 0,
- _("%s: can make relative symbolic links only in current directory"),
- dst_path);
+ error (0, errno, "%s", dst_path);
goto un_backup;
}
+
+ return 0;
}
#endif
else if (x->hard_link)