5a5770c822896655973d1ac0bff8ea7b76b88f04
[debian/tar] / gnu / linkat.c
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-2013 Free Software Foundation, Inc.
5
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.
10
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.
15
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/>.  */
18
19 /* written by Eric Blake */
20
21 #include <config.h>
22
23 #include <unistd.h>
24
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <limits.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/stat.h>
31
32 #include "areadlink.h"
33 #include "dirname.h"
34 #include "filenamecat.h"
35 #include "openat-priv.h"
36
37 #if HAVE_SYS_PARAM_H
38 # include <sys/param.h>
39 #endif
40 #ifndef MAXSYMLINKS
41 # ifdef SYMLOOP_MAX
42 #  define MAXSYMLINKS SYMLOOP_MAX
43 # else
44 #  define MAXSYMLINKS 20
45 # endif
46 #endif
47
48 #if !HAVE_LINKAT
49
50 /* Create a link.  If FILE1 is a symlink, either create a hardlink to
51    that symlink, or fake it by creating an identical symlink.  */
52 # if LINK_FOLLOWS_SYMLINKS == 0
53 #  define link_immediate link
54 # else
55 static int
56 link_immediate (char const *file1, char const *file2)
57 {
58   char *target = areadlink (file1);
59   if (target)
60     {
61       /* A symlink cannot be modified in-place.  Therefore, creating
62          an identical symlink behaves like a hard link to a symlink,
63          except for incorrect st_ino and st_nlink.  However, we must
64          be careful of EXDEV.  */
65       struct stat st1;
66       struct stat st2;
67       char *dir = mdir_name (file2);
68       if (!dir)
69         {
70           free (target);
71           errno = ENOMEM;
72           return -1;
73         }
74       if (lstat (file1, &st1) == 0 && stat (dir, &st2) == 0)
75         {
76           if (st1.st_dev == st2.st_dev)
77             {
78               int result = symlink (target, file2);
79               int saved_errno = errno;
80               free (target);
81               free (dir);
82               errno = saved_errno;
83               return result;
84             }
85           free (target);
86           free (dir);
87           errno = EXDEV;
88           return -1;
89         }
90       free (target);
91       free (dir);
92     }
93   if (errno == ENOMEM)
94     return -1;
95   return link (file1, file2);
96 }
97 # endif /* LINK_FOLLOWS_SYMLINKS == 0 */
98
99 /* Create a link.  If FILE1 is a symlink, create a hardlink to the
100    canonicalized file.  */
101 # if 0 < LINK_FOLLOWS_SYMLINKS
102 #  define link_follow link
103 # else
104 static int
105 link_follow (char const *file1, char const *file2)
106 {
107   char *name = (char *) file1;
108   char *target;
109   int result;
110   int i = MAXSYMLINKS;
111
112   /* Using realpath or canonicalize_file_name is too heavy-handed: we
113      don't need an absolute name, and we don't need to resolve
114      intermediate symlinks, just the basename of each iteration.  */
115   while (i-- && (target = areadlink (name)))
116     {
117       if (IS_ABSOLUTE_FILE_NAME (target))
118         {
119           if (name != file1)
120             free (name);
121           name = target;
122         }
123       else
124         {
125           char *dir = mdir_name (name);
126           if (name != file1)
127             free (name);
128           if (!dir)
129             {
130               free (target);
131               errno = ENOMEM;
132               return -1;
133             }
134           name = mfile_name_concat (dir, target, NULL);
135           free (dir);
136           free (target);
137           if (!name)
138             {
139               errno = ENOMEM;
140               return -1;
141             }
142         }
143     }
144   if (i < 0)
145     {
146       target = NULL;
147       errno = ELOOP;
148     }
149   if (!target && errno != EINVAL)
150     {
151       if (name != file1)
152         {
153           int saved_errno = errno;
154           free (name);
155           errno = saved_errno;
156         }
157       return -1;
158     }
159   result = link (name, file2);
160   if (name != file1)
161     {
162       int saved_errno = errno;
163       free (name);
164       errno = saved_errno;
165     }
166   return result;
167 }
168 # endif /* 0 < LINK_FOLLOWS_SYMLINKS */
169
170 /* On Solaris, link() doesn't follow symlinks by default, but does so as soon
171    as a library or executable takes part in the program that has been compiled
172    with "c99" or "cc -xc99=all" or "cc ... /usr/lib/values-xpg4.o ...".  */
173 # if LINK_FOLLOWS_SYMLINKS == -1
174
175 /* Reduce the penalty of link_immediate and link_follow by incorporating the
176    knowledge that link()'s behaviour depends on the __xpg4 variable.  */
177 extern int __xpg4;
178
179 static int
180 solaris_optimized_link_immediate (char const *file1, char const *file2)
181 {
182   if (__xpg4 == 0)
183     return link (file1, file2);
184   return link_immediate (file1, file2);
185 }
186
187 static int
188 solaris_optimized_link_follow (char const *file1, char const *file2)
189 {
190   if (__xpg4 != 0)
191     return link (file1, file2);
192   return link_follow (file1, file2);
193 }
194
195 #  define link_immediate solaris_optimized_link_immediate
196 #  define link_follow solaris_optimized_link_follow
197
198 # endif
199
200 /* Create a link to FILE1, in the directory open on descriptor FD1, to FILE2,
201    in the directory open on descriptor FD2.  If FILE1 is a symlink, FLAG
202    controls whether to dereference FILE1 first.  If possible, do it without
203    changing the working directory.  Otherwise, resort to using
204    save_cwd/fchdir, then rename/restore_cwd.  If either the save_cwd or
205    the restore_cwd fails, then give a diagnostic and exit nonzero.  */
206
207 int
208 linkat (int fd1, char const *file1, int fd2, char const *file2, int flag)
209 {
210   if (flag & ~AT_SYMLINK_FOLLOW)
211     {
212       errno = EINVAL;
213       return -1;
214     }
215   return at_func2 (fd1, file1, fd2, file2,
216                    flag ? link_follow : link_immediate);
217 }
218
219 #else /* HAVE_LINKAT */
220
221 # undef linkat
222
223 /* Create a link.  If FILE1 is a symlink, create a hardlink to the
224    canonicalized file.  */
225
226 static int
227 linkat_follow (int fd1, char const *file1, int fd2, char const *file2)
228 {
229   char *name = (char *) file1;
230   char *target;
231   int result;
232   int i = MAXSYMLINKS;
233
234   /* There is no realpathat.  */
235   while (i-- && (target = areadlinkat (fd1, name)))
236     {
237       if (IS_ABSOLUTE_FILE_NAME (target))
238         {
239           if (name != file1)
240             free (name);
241           name = target;
242         }
243       else
244         {
245           char *dir = mdir_name (name);
246           if (name != file1)
247             free (name);
248           if (!dir)
249             {
250               free (target);
251               errno = ENOMEM;
252               return -1;
253             }
254           name = mfile_name_concat (dir, target, NULL);
255           free (dir);
256           free (target);
257           if (!name)
258             {
259               errno = ENOMEM;
260               return -1;
261             }
262         }
263     }
264   if (i < 0)
265     {
266       target = NULL;
267       errno = ELOOP;
268     }
269   if (!target && errno != EINVAL)
270     {
271       if (name != file1)
272         {
273           int saved_errno = errno;
274           free (name);
275           errno = saved_errno;
276         }
277       return -1;
278     }
279   result = linkat (fd1, name, fd2, file2, 0);
280   if (name != file1)
281     {
282       int saved_errno = errno;
283       free (name);
284       errno = saved_errno;
285     }
286   return result;
287 }
288
289
290 /* Like linkat, but guarantee that AT_SYMLINK_FOLLOW works even on
291    older Linux kernels.  */
292
293 int
294 rpl_linkat (int fd1, char const *file1, int fd2, char const *file2, int flag)
295 {
296   if (flag & ~AT_SYMLINK_FOLLOW)
297     {
298       errno = EINVAL;
299       return -1;
300     }
301
302 # if LINKAT_TRAILING_SLASH_BUG
303   /* Reject trailing slashes on non-directories.  */
304   {
305     size_t len1 = strlen (file1);
306     size_t len2 = strlen (file2);
307     if ((len1 && file1[len1 - 1] == '/')
308         || (len2 && file2[len2 - 1] == '/'))
309       {
310         /* Let linkat() decide whether hard-linking directories is legal.
311            If fstatat() fails, then linkat() should fail for the same reason;
312            if fstatat() succeeds, require a directory.  */
313         struct stat st;
314         if (fstatat (fd1, file1, &st, flag ? 0 : AT_SYMLINK_NOFOLLOW))
315           return -1;
316         if (!S_ISDIR (st.st_mode))
317           {
318             errno = ENOTDIR;
319             return -1;
320           }
321       }
322   }
323 # endif
324
325   if (!flag)
326     return linkat (fd1, file1, fd2, file2, flag);
327
328   /* Cache the information on whether the system call really works.  */
329   {
330     static int have_follow_really; /* 0 = unknown, 1 = yes, -1 = no */
331     if (0 <= have_follow_really)
332     {
333       int result = linkat (fd1, file1, fd2, file2, flag);
334       if (!(result == -1 && errno == EINVAL))
335         {
336           have_follow_really = 1;
337           return result;
338         }
339       have_follow_really = -1;
340     }
341   }
342   return linkat_follow (fd1, file1, fd2, file2);
343 }
344
345 #endif /* HAVE_LINKAT */