1 /* -*- buffer-read-only: t -*- vi: set ro: */
2 /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
3 /* Create a hard link relative to open directories.
4 Copyright (C) 2009-2011 Free Software Foundation, Inc.
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 /* written by Eric Blake */
33 #include "areadlink.h"
35 #include "filenamecat.h"
36 #include "openat-priv.h"
39 # include <sys/param.h>
43 # define MAXSYMLINKS SYMLOOP_MAX
45 # define MAXSYMLINKS 20
51 /* Create a link. If FILE1 is a symlink, either create a hardlink to
52 that symlink, or fake it by creating an identical symlink. */
53 # if LINK_FOLLOWS_SYMLINKS == 0
54 # define link_immediate link
57 link_immediate (char const *file1, char const *file2)
59 char *target = areadlink (file1);
62 /* A symlink cannot be modified in-place. Therefore, creating
63 an identical symlink behaves like a hard link to a symlink,
64 except for incorrect st_ino and st_nlink. However, we must
65 be careful of EXDEV. */
68 char *dir = mdir_name (file2);
75 if (lstat (file1, &st1) == 0 && stat (dir, &st2) == 0)
77 if (st1.st_dev == st2.st_dev)
79 int result = symlink (target, file2);
80 int saved_errno = errno;
96 return link (file1, file2);
98 # endif /* LINK_FOLLOWS_SYMLINKS == 0 */
100 /* Create a link. If FILE1 is a symlink, create a hardlink to the
101 canonicalized file. */
102 # if 0 < LINK_FOLLOWS_SYMLINKS
103 # define link_follow link
106 link_follow (char const *file1, char const *file2)
108 char *name = (char *) file1;
113 /* Using realpath or canonicalize_file_name is too heavy-handed: we
114 don't need an absolute name, and we don't need to resolve
115 intermediate symlinks, just the basename of each iteration. */
116 while (i-- && (target = areadlink (name)))
118 if (IS_ABSOLUTE_FILE_NAME (target))
126 char *dir = mdir_name (name);
135 name = mfile_name_concat (dir, target, NULL);
150 if (!target && errno != EINVAL)
154 int saved_errno = errno;
160 result = link (name, file2);
163 int saved_errno = errno;
169 # endif /* 0 < LINK_FOLLOWS_SYMLINKS */
171 /* On Solaris, link() doesn't follow symlinks by default, but does so as soon
172 as a library or executable takes part in the program that has been compiled
173 with "c99" or "cc -xc99=all" or "cc ... /usr/lib/values-xpg4.o ...". */
174 # if LINK_FOLLOWS_SYMLINKS == -1
176 /* Reduce the penalty of link_immediate and link_follow by incorporating the
177 knowledge that link()'s behaviour depends on the __xpg4 variable. */
181 solaris_optimized_link_immediate (char const *file1, char const *file2)
184 return link (file1, file2);
185 return link_immediate (file1, file2);
189 solaris_optimized_link_follow (char const *file1, char const *file2)
192 return link (file1, file2);
193 return link_follow (file1, file2);
196 # define link_immediate solaris_optimized_link_immediate
197 # define link_follow solaris_optimized_link_follow
201 /* Create a link to FILE1, in the directory open on descriptor FD1, to FILE2,
202 in the directory open on descriptor FD2. If FILE1 is a symlink, FLAG
203 controls whether to dereference FILE1 first. If possible, do it without
204 changing the working directory. Otherwise, resort to using
205 save_cwd/fchdir, then rename/restore_cwd. If either the save_cwd or
206 the restore_cwd fails, then give a diagnostic and exit nonzero. */
209 linkat (int fd1, char const *file1, int fd2, char const *file2, int flag)
211 if (flag & ~AT_SYMLINK_FOLLOW)
216 return at_func2 (fd1, file1, fd2, file2,
217 flag ? link_follow : link_immediate);
220 #else /* HAVE_LINKAT */
224 /* Create a link. If FILE1 is a symlink, create a hardlink to the
225 canonicalized file. */
228 linkat_follow (int fd1, char const *file1, int fd2, char const *file2)
230 char *name = (char *) file1;
235 /* There is no realpathat. */
236 while (i-- && (target = areadlinkat (fd1, name)))
238 if (IS_ABSOLUTE_FILE_NAME (target))
246 char *dir = mdir_name (name);
255 name = mfile_name_concat (dir, target, NULL);
270 if (!target && errno != EINVAL)
274 int saved_errno = errno;
280 result = linkat (fd1, name, fd2, file2, 0);
283 int saved_errno = errno;
291 /* Like linkat, but guarantee that AT_SYMLINK_FOLLOW works even on
292 older Linux kernels. */
295 rpl_linkat (int fd1, char const *file1, int fd2, char const *file2, int flag)
297 if (flag & ~AT_SYMLINK_FOLLOW)
303 # if LINKAT_TRAILING_SLASH_BUG
304 /* Reject trailing slashes on non-directories. */
306 size_t len1 = strlen (file1);
307 size_t len2 = strlen (file2);
308 if ((len1 && file1[len1 - 1] == '/')
309 || (len2 && file2[len2 - 1] == '/'))
311 /* Let linkat() decide whether hard-linking directories is legal.
312 If fstatat() fails, then linkat() should fail for the same reason;
313 if fstatat() succeeds, require a directory. */
315 if (fstatat (fd1, file1, &st, flag ? 0 : AT_SYMLINK_NOFOLLOW))
317 if (!S_ISDIR (st.st_mode))
327 return linkat (fd1, file1, fd2, file2, flag);
329 /* Cache the information on whether the system call really works. */
331 static int have_follow_really; /* 0 = unknown, 1 = yes, -1 = no */
332 if (0 <= have_follow_really)
334 int result = linkat (fd1, file1, fd2, file2, flag);
335 if (!(result == -1 && errno == EINVAL))
337 have_follow_really = 1;
340 have_follow_really = -1;
343 return linkat_follow (fd1, file1, fd2, file2);
346 #endif /* HAVE_LINKAT */