root/maint/gnulib/lib/lchown.c

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

DEFINITIONS

This source file includes following definitions.
  1. lchown
  2. rpl_lchown

   1 /* Provide a stub lchown function for systems that lack it.
   2 
   3    Copyright (C) 1998-1999, 2002, 2004, 2006-2007, 2009-2021 Free Software
   4    Foundation, Inc.
   5 
   6    This file is free software: you can redistribute it and/or modify
   7    it under the terms of the GNU Lesser General Public License as
   8    published by the Free Software Foundation; either version 2.1 of the
   9    License, or (at your option) any later version.
  10 
  11    This file is distributed in the hope that it will be useful,
  12    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14    GNU Lesser General Public License for more details.
  15 
  16    You should have received a copy of the GNU Lesser General Public License
  17    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
  18 
  19 /* written by Jim Meyering */
  20 
  21 #include <config.h>
  22 
  23 #include <unistd.h>
  24 
  25 #include <errno.h>
  26 #include <stdbool.h>
  27 #include <string.h>
  28 #include <sys/stat.h>
  29 
  30 #if !HAVE_LCHOWN
  31 
  32 /* If the system chown does not follow symlinks, we don't want it
  33    replaced by gnulib's chown, which does follow symlinks.  */
  34 # if CHOWN_MODIFIES_SYMLINK
  35 #  undef chown
  36 # endif
  37 
  38 /* Work just like chown, except when FILE is a symbolic link.
  39    In that case, set errno to EOPNOTSUPP and return -1.
  40    But if autoconf tests determined that chown modifies
  41    symlinks, then just call chown.  */
  42 
  43 int
  44 lchown (const char *file, uid_t uid, gid_t gid)
     /* [previous][next][first][last][top][bottom][index][help] */
  45 {
  46 # if HAVE_CHOWN
  47 #  if ! CHOWN_MODIFIES_SYMLINK
  48   struct stat stats;
  49 
  50   if (lstat (file, &stats) == 0 && S_ISLNK (stats.st_mode))
  51     {
  52       errno = EOPNOTSUPP;
  53       return -1;
  54     }
  55 #  endif
  56 
  57   return chown (file, uid, gid);
  58 
  59 # else /* !HAVE_CHOWN */
  60   errno = ENOSYS;
  61   return -1;
  62 # endif
  63 }
  64 
  65 #else /* HAVE_LCHOWN */
  66 
  67 # undef lchown
  68 
  69 /* Work around trailing slash bugs in lchown.  */
  70 int
  71 rpl_lchown (const char *file, uid_t uid, gid_t gid)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73   bool stat_valid = false;
  74   int result;
  75 
  76 # if CHOWN_CHANGE_TIME_BUG
  77   struct stat st;
  78 
  79   if (gid != (gid_t) -1 || uid != (uid_t) -1)
  80     {
  81       if (lstat (file, &st))
  82         return -1;
  83       stat_valid = true;
  84       if (!S_ISLNK (st.st_mode))
  85         return chown (file, uid, gid);
  86     }
  87 # endif
  88 
  89 # if CHOWN_TRAILING_SLASH_BUG
  90   if (!stat_valid)
  91     {
  92       size_t len = strlen (file);
  93       if (len && file[len - 1] == '/')
  94         return chown (file, uid, gid);
  95     }
  96 # endif
  97 
  98   result = lchown (file, uid, gid);
  99 
 100 # if CHOWN_CHANGE_TIME_BUG && HAVE_LCHMOD
 101   if (result == 0 && stat_valid
 102       && (uid == st.st_uid || uid == (uid_t) -1)
 103       && (gid == st.st_gid || gid == (gid_t) -1))
 104     {
 105       /* No change in ownership, but at least one argument was not -1,
 106          so we are required to update ctime.  Since lchown succeeded,
 107          we assume that lchmod will do likewise.  But if the system
 108          lacks lchmod and lutimes, we are out of luck.  Oh well.  */
 109       result = lchmod (file, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO
 110                                            | S_ISUID | S_ISGID | S_ISVTX));
 111     }
 112 # endif
 113 
 114   return result;
 115 }
 116 
 117 #endif /* HAVE_LCHOWN */

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