1 /* -*- buffer-read-only: t -*- vi: set ro: */
2 /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
3 /* Emulate link on platforms that lack it, namely native Windows platforms.
5 Copyright (C) 2009-2013 Free Software Foundation, Inc.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>. */
30 # if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
32 # define WIN32_LEAN_AND_MEAN
35 /* CreateHardLink was introduced only in Windows 2000. */
36 typedef BOOL (WINAPI * CreateHardLinkFuncType) (LPCTSTR lpFileName,
37 LPCTSTR lpExistingFileName,
38 LPSECURITY_ATTRIBUTES lpSecurityAttributes);
39 static CreateHardLinkFuncType CreateHardLinkFunc = NULL;
40 static BOOL initialized = FALSE;
45 HMODULE kernel32 = GetModuleHandle ("kernel32.dll");
49 (CreateHardLinkFuncType) GetProcAddress (kernel32, "CreateHardLinkA");
55 link (const char *file1, const char *file2)
58 size_t len1 = strlen (file1);
59 size_t len2 = strlen (file2);
62 if (CreateHardLinkFunc == NULL)
64 /* System does not support hard links. */
68 /* Reject trailing slashes on non-directories; mingw does not
69 support hard-linking directories. */
70 if ((len1 && (file1[len1 - 1] == '/' || file1[len1 - 1] == '\\'))
71 || (len2 && (file2[len2 - 1] == '/' || file2[len2 - 1] == '\\')))
74 if (stat (file1, &st) == 0 && S_ISDIR (st.st_mode))
80 /* CreateHardLink("b/.","a",NULL) creates file "b", so we must check
81 that dirname(file2) exists. */
87 char *p = strchr (dir, '\0');
88 while (dir < p && (*--p != '/' && *p != '\\'));
90 if (p != dir && stat (dir, &st) == -1)
92 int saved_errno = errno;
99 /* Now create the link. */
100 if (CreateHardLinkFunc (file2, file1, NULL) == 0)
102 /* It is not documented which errors CreateHardLink() can produce.
103 * The following conversions are based on tests on a Windows XP SP2
105 DWORD err = GetLastError ();
108 case ERROR_ACCESS_DENIED:
112 case ERROR_INVALID_FUNCTION: /* fs does not support hard links */
116 case ERROR_NOT_SAME_DEVICE:
120 case ERROR_PATH_NOT_FOUND:
121 case ERROR_FILE_NOT_FOUND:
125 case ERROR_INVALID_PARAMETER:
126 errno = ENAMETOOLONG;
129 case ERROR_TOO_MANY_LINKS:
133 case ERROR_ALREADY_EXISTS:
146 # else /* !Windows */
148 # error "This platform lacks a link function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib."
150 # endif /* !Windows */
151 #else /* HAVE_LINK */
155 /* Create a hard link from FILE1 to FILE2, working around platform bugs. */
157 rpl_link (char const *file1, char const *file2)
163 /* Don't allow IRIX to dereference dangling file2 symlink. */
164 if (!lstat (file2, &st))
170 /* Reject trailing slashes on non-directories. */
171 len1 = strlen (file1);
172 len2 = strlen (file2);
173 if ((len1 && file1[len1 - 1] == '/')
174 || (len2 && file2[len2 - 1] == '/'))
176 /* Let link() decide whether hard-linking directories is legal.
177 If stat() fails, then link() should fail for the same reason
178 (although on Solaris 9, link("file/","oops") mistakenly
179 succeeds); if stat() succeeds, require a directory. */
180 if (stat (file1, &st))
182 if (!S_ISDIR (st.st_mode))
190 /* Fix Cygwin 1.5.x bug where link("a","b/.") creates file "b". */
191 char *dir = strdup (file2);
195 /* We already know file2 does not end in slash. Strip off the
196 basename, then check that the dirname exists. */
197 p = strrchr (dir, '/');
201 if (stat (dir, &st) == -1)
203 int saved_errno = errno;
211 return link (file1, file2);
213 #endif /* HAVE_LINK */