~ubuntu-branches/ubuntu/vivid/gzip/vivid

« back to all changes in this revision

Viewing changes to lib/lchown.c

  • Committer: Steve Langasek
  • Date: 2012-06-29 02:07:40 UTC
  • mfrom: (4.1.9 sid)
  • Revision ID: steve.langasek@canonical.com-20120629020740-qqikrblzana08v2y
Merge version 1.5-1.1 from Debian

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Provide a stub lchown function for systems that lack it.
2
 
 
3
 
   Copyright (C) 1998-1999, 2002, 2004, 2006-2007, 2009-2010 Free Software
4
 
   Foundation, Inc.
5
 
 
6
 
   This program is free software: you can redistribute it and/or modify
7
 
   it under the terms of the GNU General Public License as published by
8
 
   the Free Software Foundation; either version 3 of the License, or
9
 
   (at your option) any later version.
10
 
 
11
 
   This program 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 General Public License for more details.
15
 
 
16
 
   You should have received a copy of the GNU General Public License
17
 
   along with this program.  If not, see <http://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)
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)
72
 
{
73
 
  struct stat st;
74
 
  bool stat_valid = false;
75
 
  int result;
76
 
 
77
 
# if CHOWN_CHANGE_TIME_BUG
78
 
  if (gid != (gid_t) -1 || uid != (uid_t) -1)
79
 
    {
80
 
      if (lstat (file, &st))
81
 
        return -1;
82
 
      stat_valid = true;
83
 
      if (!S_ISLNK (st.st_mode))
84
 
        return chown (file, uid, gid);
85
 
    }
86
 
# endif
87
 
 
88
 
# if CHOWN_TRAILING_SLASH_BUG
89
 
  if (!stat_valid)
90
 
    {
91
 
      size_t len = strlen (file);
92
 
      if (len && file[len - 1] == '/')
93
 
        return chown (file, uid, gid);
94
 
    }
95
 
# endif
96
 
 
97
 
  result = lchown (file, uid, gid);
98
 
 
99
 
# if CHOWN_CHANGE_TIME_BUG && HAVE_LCHMOD
100
 
  if (result == 0 && stat_valid
101
 
      && (uid == st.st_uid || uid == (uid_t) -1)
102
 
      && (gid == st.st_gid || gid == (gid_t) -1))
103
 
    {
104
 
      /* No change in ownership, but at least one argument was not -1,
105
 
         so we are required to update ctime.  Since lchown succeeded,
106
 
         we assume that lchmod will do likewise.  But if the system
107
 
         lacks lchmod and lutimes, we are out of luck.  Oh well.  */
108
 
      result = lchmod (file, st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO
109
 
                                           | S_ISUID | S_ISGID | S_ISVTX));
110
 
    }
111
 
# endif
112
 
 
113
 
  return result;
114
 
}
115
 
 
116
 
#endif /* HAVE_LCHOWN */