diff options
author | Jim Meyering <jim@meyering.net> | 1998-07-03 20:32:37 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 1998-07-03 20:32:37 +0000 |
commit | def9c2bf0b13346d3f316d0e73f3ce4c62262c9d (patch) | |
tree | 37d4de6278b792208be78bbe3d2a0863b74c9c34 /src/copy.c | |
parent | 6191d1839ae99ad917f6584739c9543cb1de2ff7 (diff) | |
download | coreutils-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.c | 38 |
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) |