root/maint/gnulib/lib/symlinkat.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rpl_symlinkat
  2. symlinkat
  3. symlink_reversed
  4. symlinkat

   1 /* Create a symlink relative to an open directory.
   2    Copyright (C) 2009-2021 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 <https://www.gnu.org/licenses/>.  */
  16 
  17 /* written by Eric Blake */
  18 
  19 #include <config.h>
  20 
  21 /* Specification.  */
  22 #include <unistd.h>
  23 
  24 #include <errno.h>
  25 #include <stdlib.h>
  26 
  27 #if HAVE_SYMLINKAT
  28 # undef symlinkat
  29 
  30 #include <fcntl.h>
  31 #include <sys/stat.h>
  32 #include <string.h>
  33 
  34 /* Create a symlink, but reject trailing slash.  */
  35 int
  36 rpl_symlinkat (char const *contents, int fd, char const *name)
     /* [previous][next][first][last][top][bottom][index][help] */
  37 {
  38   size_t len = strlen (name);
  39   if (len && name[len - 1] == '/')
  40     {
  41       struct stat st;
  42       if (fstatat (fd, name, &st, AT_SYMLINK_NOFOLLOW) == 0
  43           || errno == EOVERFLOW)
  44         errno = EEXIST;
  45       return -1;
  46     }
  47   return symlinkat (contents, fd, name);
  48 }
  49 
  50 #elif !HAVE_SYMLINK
  51 /* Mingw lacks symlink, and it is more efficient to provide a trivial
  52    wrapper than to go through at-func.c to call rpl_symlink.  */
  53 
  54 int
  55 symlinkat (_GL_UNUSED char const *path1, _GL_UNUSED int fd,
     /* [previous][next][first][last][top][bottom][index][help] */
  56            _GL_UNUSED char const *path2)
  57 {
  58   errno = ENOSYS;
  59   return -1;
  60 }
  61 
  62 #else /* HAVE_SYMLINK */
  63 
  64 /* Our openat helper functions expect the directory parameter first,
  65    not second.  These shims make life easier.  */
  66 
  67 /* Like symlink, but with arguments reversed.  */
  68 static int
  69 symlink_reversed (char const *file, char const *contents)
     /* [previous][next][first][last][top][bottom][index][help] */
  70 {
  71   return symlink (contents, file);
  72 }
  73 
  74 /* Like symlinkat, but with arguments reversed.  */
  75 
  76 static int
  77 symlinkat_reversed (int fd, char const *file, char const *contents);
  78 
  79 # define AT_FUNC_NAME symlinkat_reversed
  80 # define AT_FUNC_F1 symlink_reversed
  81 # define AT_FUNC_POST_FILE_PARAM_DECLS , char const *contents
  82 # define AT_FUNC_POST_FILE_ARGS        , contents
  83 # include "at-func.c"
  84 # undef AT_FUNC_NAME
  85 # undef AT_FUNC_F1
  86 # undef AT_FUNC_POST_FILE_PARAM_DECLS
  87 # undef AT_FUNC_POST_FILE_ARGS
  88 
  89 /* Create a symlink FILE, in the directory open on descriptor FD,
  90    holding CONTENTS.  If possible, do it without changing the
  91    working directory.  Otherwise, resort to using save_cwd/fchdir,
  92    then symlink/restore_cwd.  If either the save_cwd or the restore_cwd
  93    fails, then give a diagnostic and exit nonzero.  */
  94 
  95 int
  96 symlinkat (char const *contents, int fd, char const *file)
     /* [previous][next][first][last][top][bottom][index][help] */
  97 {
  98   return symlinkat_reversed (fd, file, contents);
  99 }
 100 
 101 #endif /* HAVE_SYMLINK */

/* [previous][next][first][last][top][bottom][index][help] */