~ubuntu-branches/ubuntu/utopic/coreutils/utopic-proposed

« back to all changes in this revision

Viewing changes to lib/euidaccess-stat.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2012-11-28 03:03:42 UTC
  • mfrom: (8.3.4 sid)
  • Revision ID: package-import@ubuntu.com-20121128030342-21zanj8354gas5gr
Tags: 8.20-3ubuntu1
* Resynchronise with Debian.  Remaining changes:
  - Make 'uname -i -p' return the real processor/hardware, instead of
    unknown.
  - Build-depend on gettext:any instead of on gettext, so that apt-get can
    properly resolve build-dependencies on the tool when cross-building.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* euidaccess-stat -- check if effective user id can access lstat'd file
2
 
   This function is probably useful only for choosing whether to issue
3
 
   a prompt in an implementation of POSIX-specified rm.
4
 
 
5
 
   Copyright (C) 2005-2006, 2009-2011 Free Software Foundation, Inc.
6
 
 
7
 
   This program is free software: you can redistribute it and/or modify
8
 
   it under the terms of the GNU General Public License as published by
9
 
   the Free Software Foundation, either version 3 of the License, or
10
 
   (at your option) any later version.
11
 
 
12
 
   This program is distributed in the hope that it will be useful,
13
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
   GNU General Public License for more details.
16
 
 
17
 
   You should have received a copy of the GNU General Public License
18
 
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
 
 
20
 
/* Adapted for use in GNU remove.c by Jim Meyering.  */
21
 
 
22
 
#include <config.h>
23
 
 
24
 
#include "euidaccess-stat.h"
25
 
 
26
 
#include <unistd.h>
27
 
 
28
 
#include "stat-macros.h"
29
 
 
30
 
/* Return true if the current user has permission of type MODE
31
 
   on the file from which stat buffer *ST was obtained, ignoring
32
 
   ACLs, attributes, `read-only'ness, etc...
33
 
   Otherwise, return false.
34
 
 
35
 
   Like the reentrant version of euidaccess, but starting with
36
 
   a stat buffer rather than a file name.  Hence, this function
37
 
   never calls access or accessx, and doesn't take into account
38
 
   whether the file has ACLs or other attributes, or resides on
39
 
   a read-only file system.  */
40
 
 
41
 
bool
42
 
euidaccess_stat (struct stat const *st, int mode)
43
 
{
44
 
  uid_t euid;
45
 
  unsigned int granted;
46
 
 
47
 
  /* Convert the mode to traditional form, clearing any bogus bits.  */
48
 
  if (R_OK == 4 && W_OK == 2 && X_OK == 1 && F_OK == 0)
49
 
    mode &= 7;
50
 
  else
51
 
    mode = ((mode & R_OK ? 4 : 0)
52
 
            + (mode & W_OK ? 2 : 0)
53
 
            + (mode & X_OK ? 1 : 0));
54
 
 
55
 
  if (mode == 0)
56
 
    return true;                /* The file exists.  */
57
 
 
58
 
  euid = geteuid ();
59
 
 
60
 
  /* The super-user can read and write any file, and execute any file
61
 
     that anyone can execute.  */
62
 
  if (euid == 0 && ((mode & X_OK) == 0
63
 
                    || (st->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
64
 
    return true;
65
 
 
66
 
  /* Convert the file's permission bits to traditional form.  */
67
 
  if (   S_IRUSR == (4 << 6)
68
 
      && S_IWUSR == (2 << 6)
69
 
      && S_IXUSR == (1 << 6)
70
 
      && S_IRGRP == (4 << 3)
71
 
      && S_IWGRP == (2 << 3)
72
 
      && S_IXGRP == (1 << 3)
73
 
      && S_IROTH == (4 << 0)
74
 
      && S_IWOTH == (2 << 0)
75
 
      && S_IXOTH == (1 << 0))
76
 
    granted = st->st_mode;
77
 
  else
78
 
    granted = (  (st->st_mode & S_IRUSR ? 4 << 6 : 0)
79
 
               + (st->st_mode & S_IWUSR ? 2 << 6 : 0)
80
 
               + (st->st_mode & S_IXUSR ? 1 << 6 : 0)
81
 
               + (st->st_mode & S_IRGRP ? 4 << 3 : 0)
82
 
               + (st->st_mode & S_IWGRP ? 2 << 3 : 0)
83
 
               + (st->st_mode & S_IXGRP ? 1 << 3 : 0)
84
 
               + (st->st_mode & S_IROTH ? 4 << 0 : 0)
85
 
               + (st->st_mode & S_IWOTH ? 2 << 0 : 0)
86
 
               + (st->st_mode & S_IXOTH ? 1 << 0 : 0));
87
 
 
88
 
  if (euid == st->st_uid)
89
 
    granted >>= 6;
90
 
  else
91
 
    {
92
 
      gid_t egid = getegid ();
93
 
      if (egid == st->st_gid || group_member (st->st_gid))
94
 
        granted >>= 3;
95
 
    }
96
 
 
97
 
  if ((mode & ~granted) == 0)
98
 
    return true;
99
 
 
100
 
  return false;
101
 
}
102
 
 
103
 
 
104
 
#ifdef TEST
105
 
# include <errno.h>
106
 
# include <stdio.h>
107
 
# include <stdlib.h>
108
 
 
109
 
# include "error.h"
110
 
# define _(msg) msg
111
 
 
112
 
char *program_name;
113
 
 
114
 
int
115
 
main (int argc, char **argv)
116
 
{
117
 
  char *file;
118
 
  int mode;
119
 
  bool ok;
120
 
  struct stat st;
121
 
 
122
 
  program_name = argv[0];
123
 
  if (argc < 3)
124
 
    abort ();
125
 
  file = argv[1];
126
 
  mode = atoi (argv[2]);
127
 
  if (lstat (file, &st) != 0)
128
 
    error (EXIT_FAILURE, errno, _("cannot stat %s"), file);
129
 
 
130
 
  ok = euidaccess_stat (&st, mode);
131
 
  printf ("%s: %s\n", file, ok ? "y" : "n");
132
 
  return 0;
133
 
}
134
 
#endif