1/* Create a symlink relative to an open directory. 2 Copyright (C) 2009-2010 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#if !HAVE_SYMLINK 24/* Mingw lacks symlink, and it is more efficient to provide a trivial 25 wrapper than to go through at-func.c to call rpl_symlink. */ 26 27# include <errno.h> 28 29int 30symlinkat (char const *path1 _GL_UNUSED, int fd _GL_UNUSED, 31 char const *path2 _GL_UNUSED) 32{ 33 errno = ENOSYS; 34 return -1; 35} 36 37#else /* HAVE_SYMLINK */ 38 39/* Our openat helper functions expect the directory parameter first, 40 not second. These shims make life easier. */ 41 42/* Like symlink, but with arguments reversed. */ 43static int 44symlink_reversed (char const *file, char const *contents) 45{ 46 return symlink (contents, file); 47} 48 49/* Like symlinkat, but with arguments reversed. */ 50 51static int 52symlinkat_reversed (int fd, char const *file, char const *contents); 53 54# define AT_FUNC_NAME symlinkat_reversed 55# define AT_FUNC_F1 symlink_reversed 56# define AT_FUNC_POST_FILE_PARAM_DECLS , char const *contents 57# define AT_FUNC_POST_FILE_ARGS , contents 58# include "at-func.c" 59# undef AT_FUNC_NAME 60# undef AT_FUNC_F1 61# undef AT_FUNC_POST_FILE_PARAM_DECLS 62# undef AT_FUNC_POST_FILE_ARGS 63 64/* Create a symlink FILE, in the directory open on descriptor FD, 65 holding CONTENTS. If possible, do it without changing the 66 working directory. Otherwise, resort to using save_cwd/fchdir, 67 then symlink/restore_cwd. If either the save_cwd or the restore_cwd 68 fails, then give a diagnostic and exit nonzero. */ 69 70int 71symlinkat (char const *contents, int fd, char const *file) 72{ 73 return symlinkat_reversed (fd, file, contents); 74} 75 76#endif /* HAVE_SYMLINK */ 77 78/* Gnulib provides a readlink stub for mingw; use it for distinction 79 between EINVAL and ENOENT, rather than always failing with ENOSYS. */ 80 81/* POSIX 2008 says that unlike readlink, readlinkat returns 0 for 82 success instead of the buffer length. But this would render 83 readlinkat worthless since readlink does not guarantee a 84 NUL-terminated buffer. Assume this was a bug in POSIX. */ 85 86/* Read the contents of symlink FILE into buffer BUF of size LEN, in the 87 directory open on descriptor FD. If possible, do it without changing 88 the working directory. Otherwise, resort to using save_cwd/fchdir, 89 then readlink/restore_cwd. If either the save_cwd or the restore_cwd 90 fails, then give a diagnostic and exit nonzero. */ 91 92#define AT_FUNC_NAME readlinkat 93#define AT_FUNC_F1 readlink 94#define AT_FUNC_POST_FILE_PARAM_DECLS , char *buf, size_t len 95#define AT_FUNC_POST_FILE_ARGS , buf, len 96#define AT_FUNC_RESULT ssize_t 97#include "at-func.c" 98#undef AT_FUNC_NAME 99#undef AT_FUNC_F1 100#undef AT_FUNC_POST_FILE_PARAM_DECLS 101#undef AT_FUNC_POST_FILE_ARGS 102#undef AT_FUNC_RESULT 103