summaryrefslogtreecommitdiff
path: root/src/ln.c
diff options
context:
space:
mode:
authorJim Meyering <jim@meyering.net>1999-11-07 10:50:11 +0000
committerJim Meyering <jim@meyering.net>1999-11-07 10:50:11 +0000
commit6e8ec1114f5d26b725861d8d204bb5e1bd118ea6 (patch)
treee576080a024f1d6204c14d19e93dd6bc0d90c0de /src/ln.c
parent6cdbe935853fed5685087813f07fe689b4077ff7 (diff)
downloadcoreutils-6e8ec1114f5d26b725861d8d204bb5e1bd118ea6.tar.xz
Allow hard links to symlinks on systems that support it.
(STAT_LIKE_LINK): Define. (do_link): Use STAT_LIKE_LINK, rather than bare `stat', and perform the extra lstat only on systems where LINK_FOLLOWS_SYMLINKS.
Diffstat (limited to 'src/ln.c')
-rw-r--r--src/ln.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/src/ln.c b/src/ln.c
index b0c1149eb..d5db093b8 100644
--- a/src/ln.c
+++ b/src/ln.c
@@ -49,6 +49,20 @@ int link (); /* Some systems don't declare this anywhere. */
int symlink ();
#endif
+/* In being careful not even to try to make hard links to directories,
+ we have to know whether link(2) follows symlinks. If it does, then
+ we have to *stat* the `source' to see if the resulting link would be
+ to a directory. Otherwise, we have to use *lstat* so that we allow
+ users to make hard links to symlinks-that-point-to-directories. */
+
+#if LINK_FOLLOWS_SYMLINKS
+# define STAT_LIKE_LINK(File, Stat_buf) \
+ stat (File, Stat_buf)
+#else
+# define STAT_LIKE_LINK(File, Stat_buf) \
+ lstat (File, Stat_buf)
+#endif
+
/* Construct a string NEW_DEST by concatenating DEST, a slash, and
basename(SOURCE) in alloca'd memory. Don't modify DEST or SOURCE. */
@@ -144,17 +158,23 @@ do_link (const char *source, const char *dest)
On other systems, link follows symlinks, so this check is right. */
if (!symbolic_link)
{
- if (stat (source, &source_stats) != 0)
+ if (STAT_LIKE_LINK (source, &source_stats) != 0)
{
+#if LINK_FOLLOWS_SYMLINKS
/* This still could be a legitimate request:
if SOURCE is a dangling symlink. */
- if (errno != ENOENT
- || lstat (source, &source_stats) != 0)
+ if (errno == ENOENT && lstat (source, &source_stats) == 0)
+ {
+ /* FIXME: Consider giving a warning that this is not portable. */
+ }
+ else
+#endif
{
error (0, errno, "%s", source);
return 1;
}
}
+
if (!hard_dir_link && S_ISDIR (source_stats.st_mode))
{
error (0, 0, _("%s: hard link not allowed for directory"), source);