(linenum→info "unix/slp.c:2238")

coreutils/6.9/lib/euidaccess-stat.c

    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 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 2, or (at your option)
   10:    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 along
   18:    with this program; if not, write to the Free Software Foundation,
   19:    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
   20: 
   21: /* Adapted for use in GNU remove.c by Jim Meyering.  */
   22: 
   23: #include <config.h>
   24: 
   25: #include "euidaccess-stat.h"
   26: 
   27: #include <unistd.h>
   28: 
   29: #ifndef F_OK
   30: # define F_OK 0
   31: # define X_OK 1
   32: # define W_OK 2
   33: # define R_OK 4
   34: #endif
   35: 
   36: #include "group-member.h"
   37: #include "stat-macros.h"
   38: 
   39: /* Return true if the current user has permission of type MODE
   40:    on the file from which stat buffer *ST was obtained, ignoring
   41:    ACLs, attributes, `read-only'ness, etc...
   42:    Otherwise, return false.
   43: 
   44:    Like the reentrant version of euidaccess, but starting with
   45:    a stat buffer rather than a file name.  Hence, this function
   46:    never calls access or accessx, and doesn't take into account
   47:    whether the file has ACLs or other attributes, or resides on
   48:    a read-only file system.  */
   49: 
   50: bool
   51: euidaccess_stat (struct stat const *st, int mode)
   52: {
   53:   uid_t euid;
   54:   unsigned int granted;
   55: 
   56:   /* Convert the mode to traditional form, clearing any bogus bits.  */
   57:   if (R_OK == 4 && W_OK == 2 && X_OK == 1 && F_OK == 0)
   58:     mode &= 7;
   59:   else
   60:     mode = ((mode & R_OK ? 4 : 0)
   61:             + (mode & W_OK ? 2 : 0)
   62:             + (mode & X_OK ? 1 : 0));
   63: 
   64:   if (mode == 0)
   65:     return true;                /* The file exists.  */
   66: 
   67:   euid = geteuid ();
   68: 
   69:   /* The super-user can read and write any file, and execute any file
   70:      that anyone can execute.  */
   71:   if (euid == 0 && ((mode & X_OK) == 0
   72:                     || (st->st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
   73:     return true;
   74: 
   75:   /* Convert the file's permission bits to traditional form.  */
   76:   if (   S_IRUSR == (4 << 6)
   77:       && S_IWUSR == (2 << 6)
   78:       && S_IXUSR == (1 << 6)
   79:       && S_IRGRP == (4 << 3)
   80:       && S_IWGRP == (2 << 3)
   81:       && S_IXGRP == (1 << 3)
   82:       && S_IROTH == (4 << 0)
   83:       && S_IWOTH == (2 << 0)
   84:       && S_IXOTH == (1 << 0))
   85:     granted = st->st_mode;
   86:   else
   87:     granted = (  (st->st_mode & S_IRUSR ? 4 << 6 : 0)
   88:                + (st->st_mode & S_IWUSR ? 2 << 6 : 0)
   89:                + (st->st_mode & S_IXUSR ? 1 << 6 : 0)
   90:                + (st->st_mode & S_IRGRP ? 4 << 3 : 0)
   91:                + (st->st_mode & S_IWGRP ? 2 << 3 : 0)
   92:                + (st->st_mode & S_IXGRP ? 1 << 3 : 0)
   93:                + (st->st_mode & S_IROTH ? 4 << 0 : 0)
   94:                + (st->st_mode & S_IWOTH ? 2 << 0 : 0)
   95:                + (st->st_mode & S_IXOTH ? 1 << 0 : 0));
   96: 
   97:   if (euid == st->st_uid)
   98:     granted >>= 6;
   99:   else
  100:     {
  101:       gid_t egid = getegid ();
  102:       if (egid == st->st_gid || group_member (st->st_gid))
  103:         granted >>= 3;
  104:     }
  105: 
  106:   if ((mode & ~granted) == 0)
  107:     return true;
  108: 
  109:   return false;
  110: }
  111: 
  112: 
  113: #ifdef TEST
  114: # include <errno.h>
  115: # include <stdio.h>
  116: # include <stdlib.h>
  117: 
  118: # include "error.h"
  119: # define _(msg) msg
  120: 
  121: char *program_name;
  122: 
  123: int
  124: main (int argc, char **argv)
  125: {
  126:   char *file;
  127:   int mode;
  128:   bool ok;
  129:   struct stat st;
  130: 
  131:   program_name = argv[0];
  132:   if (argc < 3)
  133:     abort ();
  134:   file = argv[1];
  135:   mode = atoi (argv[2]);
  136:   if (lstat (file, &st) != 0)
  137:     error (EXIT_FAILURE, errno, _("cannot stat %s"), file);
  138: 
  139:   ok = euidaccess_stat (&st, mode);
  140:   printf ("%s: %s\n", file, ok ? "y" : "n");
  141:   exit (0);
  142: }
  143: #endif
Syntax (Markdown)