Import upstream version 1.26
[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-2011 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 <stdint.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/stat.h>
32
33 #include "areadlink.h"
34 #include "dirname.h"
35 #include "filenamecat.h"
36 #include "openat-priv.h"
37
38 #if HAVE_SYS_PARAM_H
39 # include <sys/param.h>
40 #endif
41 #ifndef MAXSYMLINKS
42 # ifdef SYMLOOP_MAX
43 #  define MAXSYMLINKS SYMLOOP_MAX
44 # else
45 #  define MAXSYMLINKS 20
46 # endif
47 #endif
48
49 #if !HAVE_LINKAT
50
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
55 # else
56 static int
57 link_immediate (char const *file1, char const *file2)
58 {
59   char *target = areadlink (file1);
60   if (target)
61     {
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.  */
66       struct stat st1;
67       struct stat st2;
68       char *dir = mdir_name (file2);
69       if (!dir)
70         {
71           free (target);
72           errno = ENOMEM;
73           return -1;
74         }
75       if (lstat (file1, &st1) == 0 && stat (dir, &st2) == 0)
76         {
77           if (st1.st_dev == st2.st_dev)
78             {
79               int result = symlink (target, file2);
80               int saved_errno = errno;
81               free (target);
82               free (dir);
83               errno = saved_errno;
84               return result;
85             }
86           free (target);
87           free (dir);
88           errno = EXDEV;
89           return -1;
90         }
91       free (target);
92       free (dir);
93     }
94   if (errno == ENOMEM)
95     return -1;
96   return link (file1, file2);
97 }
98 # endif /* LINK_FOLLOWS_SYMLINKS == 0 */
99
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
104 # else
105 static int
106 link_follow (char const *file1, char const *file2)
107 {
108   char *name = (char *) file1;
109   char *target;
110   int result;
111   int i = MAXSYMLINKS;
112
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)))
117     {
118       if (IS_ABSOLUTE_FILE_NAME (target))
119         {
120           if (name != file1)
121             free (name);
122           name = target;
123         }
124       else
125         {
126           char *dir = mdir_name (name);
127           if (name != file1)
128             free (name);
129           if (!dir)
130             {
131               free (target);
132               errno = ENOMEM;
133               return -1;
134             }
135           name = mfile_name_concat (dir, target, NULL);
136           free (dir);
137           free (target);
138           if (!name)
139             {
140               errno = ENOMEM;
141               return -1;
142             }
143         }
144     }
145   if (i < 0)
146     {
147       target = NULL;
148       errno = ELOOP;
149     }
150   if (!target && errno != EINVAL)
151     {
152       if (name != file1)
153         {
154           int saved_errno = errno;
155           free (name);
156           errno = saved_errno;
157         }
158       return -1;
159     }
160   result = link (name, file2);
161   if (name != file1)
162     {
163       int saved_errno = errno;
164       free (name);
165       errno = saved_errno;
166     }
167   return result;
168 }
169 # endif /* 0 < LINK_FOLLOWS_SYMLINKS */
170
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
175
176 /* Reduce the penalty of link_immediate and link_follow by incorporating the
177    knowledge that link()'s behaviour depends on the __xpg4 variable.  */
178 extern int __xpg4;
179
180 static int
181 solaris_optimized_link_immediate (char const *file1, char const *file2)
182 {
183   if (__xpg4 == 0)
184     return link (file1, file2);
185   return link_immediate (file1, file2);
186 }
187
188 static int
189 solaris_optimized_link_follow (char const *file1, char const *file2)
190 {
191   if (__xpg4 != 0)
192     return link (file1, file2);
193   return link_follow (file1, file2);
194 }
195
196 #  define link_immediate solaris_optimized_link_immediate
197 #  define link_follow solaris_optimized_link_follow
198
199 # endif
200
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.  */
207
208 int
209 linkat (int fd1, char const *file1, int fd2, char const *file2, int flag)
210 {
211   if (flag & ~AT_SYMLINK_FOLLOW)
212     {
213       errno = EINVAL;
214       return -1;
215     }
216   return at_func2 (fd1, file1, fd2, file2,
217                    flag ? link_follow : link_immediate);
218 }
219
220 #else /* HAVE_LINKAT */
221
222 # undef linkat
223
224 /* Create a link.  If FILE1 is a symlink, create a hardlink to the
225    canonicalized file.  */
226
227 static int
228 linkat_follow (int fd1, char const *file1, int fd2, char const *file2)
229 {
230   char *name = (char *) file1;
231   char *target;
232   int result;
233   int i = MAXSYMLINKS;
234
235   /* There is no realpathat.  */
236   while (i-- && (target = areadlinkat (fd1, name)))
237     {
238       if (IS_ABSOLUTE_FILE_NAME (target))
239         {
240           if (name != file1)
241             free (name);
242           name = target;
243         }
244       else
245         {
246           char *dir = mdir_name (name);
247           if (name != file1)
248             free (name);
249           if (!dir)
250             {
251               free (target);
252               errno = ENOMEM;
253               return -1;
254             }
255           name = mfile_name_concat (dir, target, NULL);
256           free (dir);
257           free (target);
258           if (!name)
259             {
260               errno = ENOMEM;
261               return -1;
262             }
263         }
264     }
265   if (i < 0)
266     {
267       target = NULL;
268       errno = ELOOP;
269     }
270   if (!target && errno != EINVAL)
271     {
272       if (name != file1)
273         {
274           int saved_errno = errno;
275           free (name);
276           errno = saved_errno;
277         }
278       return -1;
279     }
280   result = linkat (fd1, name, fd2, file2, 0);
281   if (name != file1)
282     {
283       int saved_errno = errno;
284       free (name);
285       errno = saved_errno;
286     }
287   return result;
288 }
289
290
291 /* Like linkat, but guarantee that AT_SYMLINK_FOLLOW works even on
292    older Linux kernels.  */
293
294 int
295 rpl_linkat (int fd1, char const *file1, int fd2, char const *file2, int flag)
296 {
297   if (flag & ~AT_SYMLINK_FOLLOW)
298     {
299       errno = EINVAL;
300       return -1;
301     }
302
303 # if LINKAT_TRAILING_SLASH_BUG
304   /* Reject trailing slashes on non-directories.  */
305   {
306     size_t len1 = strlen (file1);
307     size_t len2 = strlen (file2);
308     if ((len1 && file1[len1 - 1] == '/')
309         || (len2 && file2[len2 - 1] == '/'))
310       {
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.  */
314         struct stat st;
315         if (fstatat (fd1, file1, &st, flag ? 0 : AT_SYMLINK_NOFOLLOW))
316           return -1;
317         if (!S_ISDIR (st.st_mode))
318           {
319             errno = ENOTDIR;
320             return -1;
321           }
322       }
323   }
324 # endif
325
326   if (!flag)
327     return linkat (fd1, file1, fd2, file2, flag);
328
329   /* Cache the information on whether the system call really works.  */
330   {
331     static int have_follow_really; /* 0 = unknown, 1 = yes, -1 = no */
332     if (0 <= have_follow_really)
333     {
334       int result = linkat (fd1, file1, fd2, file2, flag);
335       if (!(result == -1 && errno == EINVAL))
336         {
337           have_follow_really = 1;
338           return result;
339         }
340       have_follow_really = -1;
341     }
342   }
343   return linkat_follow (fd1, file1, fd2, file2);
344 }
345
346 #endif /* HAVE_LINKAT */