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