annotate lib/link.c @ 17476:6057744acd2c default tip master

autoupdate
author Karl Berry <karl@freefriends.org>
date Fri, 16 Aug 2013 06:32:22 -0700
parents e542fd46ad6f
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
1 /* Emulate link on platforms that lack it, namely native Windows platforms.
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
2
17249
e542fd46ad6f maint: update all copyright year number ranges
Eric Blake <eblake@redhat.com>
parents: 16366
diff changeset
3 Copyright (C) 2009-2013 Free Software Foundation, Inc.
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
4
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
5 This program is free software; you can redistribute it and/or modify
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
6 it under the terms of the GNU General Public License as published by
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
7 the Free Software Foundation; either version 2, or (at your option)
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
8 any later version.
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
9
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
10 This program is distributed in the hope that it will be useful,
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
13 GNU General Public License for more details.
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
14
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
15 You should have received a copy of the GNU General Public License
16366
bb182ee4a09d maint: replace FSF snail-mail addresses with URLs
Paul Eggert <eggert@cs.ucla.edu>
parents: 16201
diff changeset
16 along with this program; if not, see <http://www.gnu.org/licenses/>. */
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
17
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
18 #include <config.h>
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
19
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
20 #include <unistd.h>
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
21
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
22 #include <errno.h>
11981
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
23 #include <stdlib.h>
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
24 #include <string.h>
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
25 #include <sys/stat.h>
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
26
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
27 #if !HAVE_LINK
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
28 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
29
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
30 # define WIN32_LEAN_AND_MEAN
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
31 # include <windows.h>
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
32
11063
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
33 /* CreateHardLink was introduced only in Windows 2000. */
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
34 typedef BOOL (WINAPI * CreateHardLinkFuncType) (LPCTSTR lpFileName,
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
35 LPCTSTR lpExistingFileName,
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
36 LPSECURITY_ATTRIBUTES lpSecurityAttributes);
11063
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
37 static CreateHardLinkFuncType CreateHardLinkFunc = NULL;
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
38 static BOOL initialized = FALSE;
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
39
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
40 static void
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
41 initialize (void)
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
42 {
12086
1ef8293b6bbe link: LoadLibrary is not needed.
Paolo Bonzini <bonzini@gnu.org>
parents: 12062
diff changeset
43 HMODULE kernel32 = GetModuleHandle ("kernel32.dll");
11063
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
44 if (kernel32 != NULL)
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
45 {
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
46 CreateHardLinkFunc =
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
47 (CreateHardLinkFuncType) GetProcAddress (kernel32, "CreateHardLinkA");
11063
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
48 }
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
49 initialized = TRUE;
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
50 }
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
51
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
52 int
11981
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
53 link (const char *file1, const char *file2)
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
54 {
11981
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
55 char *dir;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
56 size_t len1 = strlen (file1);
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
57 size_t len2 = strlen (file2);
11063
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
58 if (!initialized)
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
59 initialize ();
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
60 if (CreateHardLinkFunc == NULL)
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
61 {
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
62 /* System does not support hard links. */
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
63 errno = EPERM;
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
64 return -1;
2921cdaa1164 Make the 'link' module link on Windows NT 4.
Bruno Haible <bruno@clisp.org>
parents: 11041
diff changeset
65 }
11981
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
66 /* Reject trailing slashes on non-directories; mingw does not
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
67 support hard-linking directories. */
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
68 if ((len1 && (file1[len1 - 1] == '/' || file1[len1 - 1] == '\\'))
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
69 || (len2 && (file2[len2 - 1] == '/' || file2[len2 - 1] == '\\')))
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
70 {
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
71 struct stat st;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
72 if (stat (file1, &st) == 0 && S_ISDIR (st.st_mode))
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
73 errno = EPERM;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
74 else
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
75 errno = ENOTDIR;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
76 return -1;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
77 }
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
78 /* CreateHardLink("b/.","a",NULL) creates file "b", so we must check
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
79 that dirname(file2) exists. */
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
80 dir = strdup (file2);
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
81 if (!dir)
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
82 return -1;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
83 {
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
84 struct stat st;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
85 char *p = strchr (dir, '\0');
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
86 while (dir < p && (*--p != '/' && *p != '\\'));
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
87 *p = '\0';
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
88 if (p != dir && stat (dir, &st) == -1)
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
89 {
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
90 int saved_errno = errno;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
91 free (dir);
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
92 errno = saved_errno;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
93 return -1;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
94 }
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
95 free (dir);
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
96 }
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
97 /* Now create the link. */
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
98 if (CreateHardLinkFunc (file2, file1, NULL) == 0)
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
99 {
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
100 /* It is not documented which errors CreateHardLink() can produce.
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
101 * The following conversions are based on tests on a Windows XP SP2
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
102 * system. */
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
103 DWORD err = GetLastError ();
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
104 switch (err)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
105 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
106 case ERROR_ACCESS_DENIED:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
107 errno = EACCES;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
108 break;
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
109
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
110 case ERROR_INVALID_FUNCTION: /* fs does not support hard links */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
111 errno = EPERM;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
112 break;
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
113
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
114 case ERROR_NOT_SAME_DEVICE:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
115 errno = EXDEV;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
116 break;
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
117
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
118 case ERROR_PATH_NOT_FOUND:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
119 case ERROR_FILE_NOT_FOUND:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
120 errno = ENOENT;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
121 break;
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
122
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
123 case ERROR_INVALID_PARAMETER:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
124 errno = ENAMETOOLONG;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
125 break;
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
126
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
127 case ERROR_TOO_MANY_LINKS:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
128 errno = EMLINK;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
129 break;
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
130
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
131 case ERROR_ALREADY_EXISTS:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
132 errno = EEXIST;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
133 break;
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
134
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
135 default:
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
136 errno = EIO;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12086
diff changeset
137 }
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
138 return -1;
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
139 }
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
140
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
141 return 0;
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
142 }
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
143
11981
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
144 # else /* !Windows */
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
145
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
146 # error "This platform lacks a link function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib."
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
147
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
148 # endif /* !Windows */
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
149 #else /* HAVE_LINK */
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
150
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
151 # undef link
11041
894d336e6216 New module 'link'.
Martin Lambers <marlam@marlam.de>
parents:
diff changeset
152
11981
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
153 /* Create a hard link from FILE1 to FILE2, working around platform bugs. */
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
154 int
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
155 rpl_link (char const *file1, char const *file2)
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
156 {
15313
8dfa469e2ba8 link: work around IRIX bug
Eric Blake <eblake@redhat.com>
parents: 14079
diff changeset
157 size_t len1;
8dfa469e2ba8 link: work around IRIX bug
Eric Blake <eblake@redhat.com>
parents: 14079
diff changeset
158 size_t len2;
8dfa469e2ba8 link: work around IRIX bug
Eric Blake <eblake@redhat.com>
parents: 14079
diff changeset
159 struct stat st;
8dfa469e2ba8 link: work around IRIX bug
Eric Blake <eblake@redhat.com>
parents: 14079
diff changeset
160
8dfa469e2ba8 link: work around IRIX bug
Eric Blake <eblake@redhat.com>
parents: 14079
diff changeset
161 /* Don't allow IRIX to dereference dangling file2 symlink. */
8dfa469e2ba8 link: work around IRIX bug
Eric Blake <eblake@redhat.com>
parents: 14079
diff changeset
162 if (!lstat (file2, &st))
8dfa469e2ba8 link: work around IRIX bug
Eric Blake <eblake@redhat.com>
parents: 14079
diff changeset
163 {
8dfa469e2ba8 link: work around IRIX bug
Eric Blake <eblake@redhat.com>
parents: 14079
diff changeset
164 errno = EEXIST;
8dfa469e2ba8 link: work around IRIX bug
Eric Blake <eblake@redhat.com>
parents: 14079
diff changeset
165 return -1;
8dfa469e2ba8 link: work around IRIX bug
Eric Blake <eblake@redhat.com>
parents: 14079
diff changeset
166 }
8dfa469e2ba8 link: work around IRIX bug
Eric Blake <eblake@redhat.com>
parents: 14079
diff changeset
167
11981
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
168 /* Reject trailing slashes on non-directories. */
15313
8dfa469e2ba8 link: work around IRIX bug
Eric Blake <eblake@redhat.com>
parents: 14079
diff changeset
169 len1 = strlen (file1);
8dfa469e2ba8 link: work around IRIX bug
Eric Blake <eblake@redhat.com>
parents: 14079
diff changeset
170 len2 = strlen (file2);
11981
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
171 if ((len1 && file1[len1 - 1] == '/')
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
172 || (len2 && file2[len2 - 1] == '/'))
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
173 {
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
174 /* Let link() decide whether hard-linking directories is legal.
12062
00e8f52bdef4 link: fix test failure on Solaris 9
Eric Blake <ebb9@byu.net>
parents: 11981
diff changeset
175 If stat() fails, then link() should fail for the same reason
00e8f52bdef4 link: fix test failure on Solaris 9
Eric Blake <ebb9@byu.net>
parents: 11981
diff changeset
176 (although on Solaris 9, link("file/","oops") mistakenly
00e8f52bdef4 link: fix test failure on Solaris 9
Eric Blake <ebb9@byu.net>
parents: 11981
diff changeset
177 succeeds); if stat() succeeds, require a directory. */
00e8f52bdef4 link: fix test failure on Solaris 9
Eric Blake <ebb9@byu.net>
parents: 11981
diff changeset
178 if (stat (file1, &st))
00e8f52bdef4 link: fix test failure on Solaris 9
Eric Blake <ebb9@byu.net>
parents: 11981
diff changeset
179 return -1;
00e8f52bdef4 link: fix test failure on Solaris 9
Eric Blake <ebb9@byu.net>
parents: 11981
diff changeset
180 if (!S_ISDIR (st.st_mode))
11981
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
181 {
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
182 errno = ENOTDIR;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
183 return -1;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
184 }
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
185 }
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
186 else
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
187 {
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
188 /* Fix Cygwin 1.5.x bug where link("a","b/.") creates file "b". */
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
189 char *dir = strdup (file2);
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
190 char *p;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
191 if (!dir)
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
192 return -1;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
193 /* We already know file2 does not end in slash. Strip off the
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
194 basename, then check that the dirname exists. */
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
195 p = strrchr (dir, '/');
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
196 if (p)
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
197 {
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
198 *p = '\0';
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
199 if (stat (dir, &st) == -1)
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
200 {
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
201 int saved_errno = errno;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
202 free (dir);
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
203 errno = saved_errno;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
204 return -1;
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
205 }
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
206 }
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
207 free (dir);
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
208 }
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
209 return link (file1, file2);
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
210 }
7e5f9267c62e link: fix platform bugs
Eric Blake <ebb9@byu.net>
parents: 11063
diff changeset
211 #endif /* HAVE_LINK */