1 /* Create a hard link relative to open directories.
2 Copyright (C) 2009 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 /* written by Eric Blake */
30 #include "areadlink.h"
32 #include "filenamecat.h"
33 #include "openat-priv.h"
36 # include <sys/param.h>
40 # define MAXSYMLINKS SYMLOOP_MAX
42 # define MAXSYMLINKS 20
48 /* Create a link. If FILE1 is a symlink, either create a hardlink to
49 that symlink, or fake it by creating an identical symlink. */
50 # if LINK_FOLLOWS_SYMLINKS == 0
51 # define link_immediate link
54 link_immediate (char const *file1, char const *file2)
56 char *target = areadlink (file1);
59 /* A symlink cannot be modified in-place. Therefore, creating
60 an identical symlink behaves like a hard link to a symlink,
61 except for incorrect st_ino and st_nlink. However, we must
62 be careful of EXDEV. */
65 char *dir = mdir_name (file2);
72 if (lstat (file1, &st1) == 0 && stat (dir, &st2) == 0)
74 if (st1.st_dev == st2.st_dev)
76 int result = symlink (target, file2);
77 int saved_errno = errno;
93 return link (file1, file2);
95 # endif /* LINK_FOLLOWS_SYMLINKS == 0 */
97 /* Create a link. If FILE1 is a symlink, create a hardlink to the
98 canonicalized file. */
99 # if 0 < LINK_FOLLOWS_SYMLINKS
100 # define link_follow link
103 link_follow (char const *file1, char const *file2)
105 char *name = (char *) file1;
110 /* Using realpath or canonicalize_file_name is too heavy-handed: we
111 don't need an absolute name, and we don't need to resolve
112 intermediate symlinks, just the basename of each iteration. */
113 while (i-- && (target = areadlink (name)))
115 if (IS_ABSOLUTE_FILE_NAME (target))
123 char *dir = mdir_name (name);
132 name = mfile_name_concat (dir, target, NULL);
147 if (!target && errno != EINVAL)
151 int saved_errno = errno;
157 result = link (name, file2);
160 int saved_errno = errno;
166 # endif /* 0 < LINK_FOLLOWS_SYMLINKS */
168 /* Create a link to FILE1, in the directory open on descriptor FD1, to FILE2,
169 in the directory open on descriptor FD2. If FILE1 is a symlink, FLAG
170 controls whether to dereference FILE1 first. If possible, do it without
171 changing the working directory. Otherwise, resort to using
172 save_cwd/fchdir, then rename/restore_cwd. If either the save_cwd or
173 the restore_cwd fails, then give a diagnostic and exit nonzero. */
176 linkat (int fd1, char const *file1, int fd2, char const *file2, int flag)
178 if (flag & ~AT_SYMLINK_FOLLOW)
183 return at_func2 (fd1, file1, fd2, file2,
184 flag ? link_follow : link_immediate);
187 #else /* HAVE_LINKAT */
191 /* Read a symlink, like areadlink, but relative to FD. */
194 areadlinkat (int fd, char const *filename)
196 /* The initial buffer size for the link value. A power of 2
197 detects arithmetic overflow earlier, but is not required. */
198 # define INITIAL_BUF_SIZE 1024
200 /* Allocate the initial buffer on the stack. This way, in the common
201 case of a symlink of small size, we get away with a single small malloc()
202 instead of a big malloc() followed by a shrinking realloc(). */
203 char initial_buf[INITIAL_BUF_SIZE];
205 char *buffer = initial_buf;
206 size_t buf_size = sizeof (initial_buf);
210 /* Attempt to read the link into the current buffer. */
211 ssize_t link_length = readlinkat (fd, filename, buffer, buf_size);
213 /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1
214 with errno == ERANGE if the buffer is too small. */
215 if (link_length < 0 && errno != ERANGE)
217 if (buffer != initial_buf)
219 int saved_errno = errno;
226 if ((size_t) link_length < buf_size)
228 buffer[link_length++] = '\0';
230 /* Return it in a chunk of memory as small as possible. */
231 if (buffer == initial_buf)
233 buffer = (char *) malloc (link_length);
235 /* errno is ENOMEM. */
237 memcpy (buffer, initial_buf, link_length);
241 /* Shrink buffer before returning it. */
242 if ((size_t) link_length < buf_size)
244 char *smaller_buffer = (char *) realloc (buffer, link_length);
246 if (smaller_buffer != NULL)
247 buffer = smaller_buffer;
253 if (buffer != initial_buf)
256 if (SSIZE_MAX < buf_size || (SIZE_MAX / 2 < SSIZE_MAX && buf_size == 0))
261 buffer = (char *) malloc (buf_size);
263 /* errno is ENOMEM. */
268 /* Create a link. If FILE1 is a symlink, create a hardlink to the
269 canonicalized file. */
272 linkat_follow (int fd1, char const *file1, int fd2, char const *file2)
274 char *name = (char *) file1;
279 /* There is no realpathat. */
280 while (i-- && (target = areadlinkat (fd1, name)))
282 if (IS_ABSOLUTE_FILE_NAME (target))
290 char *dir = mdir_name (name);
299 name = mfile_name_concat (dir, target, NULL);
314 if (!target && errno != EINVAL)
318 int saved_errno = errno;
324 result = linkat (fd1, name, fd2, file2, 0);
327 int saved_errno = errno;
335 /* Like linkat, but guarantee that AT_SYMLINK_FOLLOW works even on
336 older Linux kernels. */
339 rpl_linkat (int fd1, char const *file1, int fd2, char const *file2, int flag)
342 return linkat (fd1, file1, fd2, file2, flag);
343 if (flag & ~AT_SYMLINK_FOLLOW)
349 /* Cache the information on whether the system call really works. */
351 static int have_follow_really; /* 0 = unknown, 1 = yes, -1 = no */
352 if (0 <= have_follow_really)
354 int result = linkat (fd1, file1, fd2, file2, flag);
355 if (!(result == -1 && errno == EINVAL))
357 have_follow_really = 1;
360 have_follow_really = -1;
363 return linkat_follow (fd1, file1, fd2, file2);
366 #endif /* HAVE_LINKAT */