I'd like to suggest a new module 'link' that provides the link(2) function for MinGW. The module is modelled after the existing fsync module.
Martin --- lib/link.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/unistd.in.h | 17 +++++++++++ m4/link.m4 | 19 ++++++++++++ m4/unistd_h.m4 | 2 + modules/link | 24 ++++++++++++++++ modules/unistd | 4 ++ 6 files changed, 149 insertions(+), 0 deletions(-) create mode 100644 lib/link.c create mode 100644 m4/link.m4 create mode 100644 modules/link diff --git a/lib/link.c b/lib/link.c new file mode 100644 index 0000000..f8ad49c --- /dev/null +++ b/lib/link.c @@ -0,0 +1,83 @@ +/* Emulate link on platforms that lack it, primarily Windows and + cross-compilers like MinGW. + + Copyright (C) 2009 Free Software Foundation, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> + +#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + +#define WIN32_LEAN_AND_MEAN +#define _WIN32_WINNT 0x0500 +#include <unistd.h> +#include <windows.h> + +#include <errno.h> + +int +link (const char *path1, const char *path2) +{ + if (CreateHardLink (path2, path1, NULL) == 0) + { + /* It is not documented which errors CreateHardLink() can produce. + * The following conversions are based on tests on a Windows XP SP2 + * system. */ + DWORD err = GetLastError (); + switch (err) + { + case ERROR_ACCESS_DENIED: + errno = EACCES; + break; + + case ERROR_INVALID_FUNCTION: /* fs does not support hard links */ + errno = EPERM; + break; + + case ERROR_NOT_SAME_DEVICE: + errno = EXDEV; + break; + + case ERROR_PATH_NOT_FOUND: + case ERROR_FILE_NOT_FOUND: + errno = ENOENT; + break; + + case ERROR_INVALID_PARAMETER: + errno = ENAMETOOLONG; + break; + + case ERROR_TOO_MANY_LINKS: + errno = EMLINK; + break; + + case ERROR_ALREADY_EXISTS: + errno = EEXIST; + break; + + default: + errno = EIO; + } + return -1; + } + + return 0; +} + +#else /* !Windows */ + +#error "This platform lacks a link function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib." + +#endif /* !Windows */ diff --git a/lib/unistd.in.h b/lib/unistd.in.h index 05778f9..8867d7b 100644 --- a/lib/unistd.in.h +++ b/lib/unistd.in.h @@ -475,6 +475,23 @@ extern int lchown (char const *file, uid_t owner, gid_t group); #endif +#if @GNULIB_LINK@ +/* Create a new link for an existing file. + Return 0 if successful, otherwise -1 and errno set. + See POSIX:2001 specification + <http://www.opengroup.org/susv3xsh/link.html>. */ +# if !...@have_link@ +extern int link (const char *path1, const char *path2); +# endif +#elif defined GNULIB_POSIXCHECK +# undef link +# define link(path1, path2) \ + (GL_LINK_WARNING ("link is unportable - " \ + "use gnulib module link for portability"), \ + link (path1, path2)) +#endif + + #if @GNULIB_LSEEK@ # if @REPLACE_LSEEK@ /* Set the offset of FD relative to SEEK_SET, SEEK_CUR, or SEEK_END. diff --git a/m4/link.m4 b/m4/link.m4 new file mode 100644 index 0000000..349d537 --- /dev/null +++ b/m4/link.m4 @@ -0,0 +1,19 @@ +# link.m4 serial 1 +dnl Copyright (C) 2009 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_LINK], +[ + AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) + AC_CHECK_FUNCS_ONCE([link]) + if test $ac_cv_func_link = no; then + HAVE_LINK=0 + AC_LIBOBJ([link]) + gl_PREREQ_LINK + fi +]) + +# Prerequisites of lib/link.c. +AC_DEFUN([gl_PREREQ_LINK], [:]) diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4 index 5685273..0878381 100644 --- a/m4/unistd_h.m4 +++ b/m4/unistd_h.m4 @@ -48,6 +48,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS], GNULIB_GETPAGESIZE=0; AC_SUBST([GNULIB_GETPAGESIZE]) GNULIB_GETUSERSHELL=0; AC_SUBST([GNULIB_GETUSERSHELL]) GNULIB_LCHOWN=0; AC_SUBST([GNULIB_LCHOWN]) + GNULIB_LINK=0; AC_SUBST([GNULIB_LINK]) GNULIB_LSEEK=0; AC_SUBST([GNULIB_LSEEK]) GNULIB_READLINK=0; AC_SUBST([GNULIB_READLINK]) GNULIB_SLEEP=0; AC_SUBST([GNULIB_SLEEP]) @@ -63,6 +64,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS], HAVE_GETHOSTNAME=1; AC_SUBST([HAVE_GETHOSTNAME]) HAVE_GETPAGESIZE=1; AC_SUBST([HAVE_GETPAGESIZE]) HAVE_GETUSERSHELL=1; AC_SUBST([HAVE_GETUSERSHELL]) + HAVE_LINK=1; AC_SUBST([HAVE_LINK]) HAVE_READLINK=1; AC_SUBST([HAVE_READLINK]) HAVE_SLEEP=1; AC_SUBST([HAVE_SLEEP]) HAVE_DECL_ENVIRON=1; AC_SUBST([HAVE_DECL_ENVIRON]) diff --git a/modules/link b/modules/link new file mode 100644 index 0000000..22f7452 --- /dev/null +++ b/modules/link @@ -0,0 +1,24 @@ +Description: +link(2) function: create a new link for an existing file + +Files: +lib/link.c +m4/link.m4 + +Depends-on: +unistd + +configure.ac: +gl_FUNC_LINK +gl_UNISTD_MODULE_INDICATOR([link]) + +Makefile.am: + +Include: +<unistd.h> + +License: +LGPLv2+ + +Maintainer: +? diff --git a/modules/unistd b/modules/unistd index 225abf9..680ec47 100644 --- a/modules/unistd +++ b/modules/unistd @@ -40,10 +40,12 @@ unistd.h: unistd.in.h -e 's|@''GNULIB_GETPAGESIZE''@|$(GNULIB_GETPAGESIZE)|g' \ -e 's|@''GNULIB_GETUSERSHELL''@|$(GNULIB_GETUSERSHELL)|g' \ -e 's|@''GNULIB_LCHOWN''@|$(GNULIB_LCHOWN)|g' \ + -e 's|@''GNULIB_LINK''@|$(GNULIB_LINK)|g' \ -e 's|@''GNULIB_LSEEK''@|$(GNULIB_LSEEK)|g' \ -e 's|@''GNULIB_READLINK''@|$(GNULIB_READLINK)|g' \ -e 's|@''GNULIB_SLEEP''@|$(GNULIB_SLEEP)|g' \ -e 's|@''GNULIB_UNISTD_H_SIGPIPE''@|$(GNULIB_UNISTD_H_SIGPIPE)|g' \ + -e 's|@''GNULIB_UNLINK''@|$(GNULIB_UNLINK)|g' \ -e 's|@''GNULIB_WRITE''@|$(GNULIB_WRITE)|g' \ -e 's|@''HAVE_DUP2''@|$(HAVE_DUP2)|g' \ -e 's|@''HAVE_EUIDACCESS''@|$(HAVE_EUIDACCESS)|g' \ @@ -54,8 +56,10 @@ unistd.h: unistd.in.h -e 's|@''HAVE_GETHOSTNAME''@|$(HAVE_GETHOSTNAME)|g' \ -e 's|@''HAVE_GETPAGESIZE''@|$(HAVE_GETPAGESIZE)|g' \ -e 's|@''HAVE_GETUSERSHELL''@|$(HAVE_GETUSERSHELL)|g' \ + -e 's|@''HAVE_LINK''@|$(HAVE_LINK)|g' \ -e 's|@''HAVE_READLINK''@|$(HAVE_READLINK)|g' \ -e 's|@''HAVE_SLEEP''@|$(HAVE_SLEEP)|g' \ + -e 's|@''HAVE_UNLINK''@|$(HAVE_UNLINK)|g' \ -e 's|@''HAVE_DECL_ENVIRON''@|$(HAVE_DECL_ENVIRON)|g' \ -e 's|@''HAVE_DECL_GETLOGIN_R''@|$(HAVE_DECL_GETLOGIN_R)|g' \ -e 's|@''HAVE_OS_H''@|$(HAVE_OS_H)|g' \ -- 1.5.6.5