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

coreutils/6.9/lib/euidaccess.c

    1: /* euidaccess -- check if effective user id can access file
    2: 
    3:    Copyright (C) 1990, 1991, 1995, 1998, 2000, 2003, 2004, 2005, 2006
    4:    Free Software Foundation, Inc.
    5: 
    6:    This file is part of the GNU C Library.
    7: 
    8:    This program is free software; you can redistribute it and/or modify
    9:    it under the terms of the GNU General Public License as published by
   10:    the Free Software Foundation; either version 2, or (at your option)
   11:    any later version.
   12: 
   13:    This program is distributed in the hope that it will be useful,
   14:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16:    GNU General Public License for more details.
   17: 
   18:    You should have received a copy of the GNU General Public License along
   19:    with this program; if not, write to the Free Software Foundation,
   20:    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
   21: 
   22: /* Written by David MacKenzie and Torbjorn Granlund.
   23:    Adapted for GNU C library by Roland McGrath.  */
   24: 
   25: #ifndef _LIBC
   26: # include <config.h>
   27: # include "euidaccess.h"
   28: #endif
   29: 
   30: #include <sys/types.h>
   31: #include <sys/stat.h>
   32: #include <unistd.h>
   33: 
   34: #if HAVE_LIBGEN_H
   35: # include <libgen.h>
   36: #endif
   37: 
   38: #include <errno.h>
   39: #ifndef __set_errno
   40: # define __set_errno(val) errno = (val)
   41: #endif
   42: 
   43: #if defined EACCES && !defined EACCESS
   44: # define EACCESS EACCES
   45: #endif
   46: 
   47: #ifndef F_OK
   48: # define F_OK 0
   49: # define X_OK 1
   50: # define W_OK 2
   51: # define R_OK 4
   52: #endif
   53: 
   54: 
   55: #ifdef _LIBC
   56: 
   57: # define access __access
   58: # define getuid __getuid
   59: # define getgid __getgid
   60: # define geteuid __geteuid
   61: # define getegid __getegid
   62: # define group_member __group_member
   63: # define euidaccess __euidaccess
   64: # undef stat
   65: # define stat stat64
   66: 
   67: #else
   68: 
   69: # include "group-member.h"
   70: 
   71: #endif
   72: 
   73: /* Return 0 if the user has permission of type MODE on FILE;
   74:    otherwise, return -1 and set `errno'.
   75:    Like access, except that it uses the effective user and group
   76:    id's instead of the real ones, and it does not always check for read-only
   77:    file system, text busy, etc.  */
   78: 
   79: int
   80: euidaccess (const char *file, int mode)
   81: {
   82: #if defined EFF_ONLY_OK
   83:   return access (file, mode | EFF_ONLY_OK);
   84: #elif defined ACC_SELF
   85:   return accessx (file, mode, ACC_SELF);
   86: #elif HAVE_EACCESS
   87:   return eaccess (file, mode);
   88: #else
   89: 
   90:   uid_t uid = getuid ();
   91:   gid_t gid = getgid ();
   92:   uid_t euid = geteuid ();
   93:   gid_t egid = getegid ();
   94:   struct stat stats;
   95: 
   96: # if HAVE_DECL_SETREGID && PREFER_NONREENTRANT_EUIDACCESS
   97: 
   98:   /* Define PREFER_NONREENTRANT_EUIDACCESS if you prefer euidaccess to
   99:      return the correct result even if this would make it
  100:      nonreentrant.  Define this only if your entire application is
  101:      safe even if the uid or gid might temporarily change.  If your
  102:      application uses signal handlers or threads it is probably not
  103:      safe.  */
  104: 
  105:   if (mode == F_OK)
  106:     return stat (file, &stats);
  107:   else
  108:     {
  109:       int result;
  110:       int saved_errno;
  111: 
  112:       if (uid != euid)
  113:         setreuid (euid, uid);
  114:       if (gid != egid)
  115:         setregid (egid, gid);
  116: 
  117:       result = access (file, mode);
  118:       saved_errno = errno;
  119: 
  120:       /* Restore them.  */
  121:       if (uid != euid)
  122:         setreuid (uid, euid);
  123:       if (gid != egid)
  124:         setregid (gid, egid);
  125: 
  126:       errno = saved_errno;
  127:       return result;
  128:     }
  129: 
  130: # else
  131: 
  132:   /* The following code assumes the traditional Unix model, and is not
  133:      correct on systems that have ACLs or the like.  However, it's
  134:      better than nothing, and it is reentrant.  */
  135: 
  136:   unsigned int granted;
  137:   if (uid == euid && gid == egid)
  138:     /* If we are not set-uid or set-gid, access does the same.  */
  139:     return access (file, mode);
  140: 
  141:   if (stat (file, &stats) != 0)
  142:     return -1;
  143: 
  144:   /* The super-user can read and write any file, and execute any file
  145:      that anyone can execute.  */
  146:   if (euid == 0 && ((mode & X_OK) == 0
  147:                     || (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
  148:     return 0;
  149: 
  150:   /* Convert the mode to traditional form, clearing any bogus bits.  */
  151:   if (R_OK == 4 && W_OK == 2 && X_OK == 1 && F_OK == 0)
  152:     mode &= 7;
  153:   else
  154:     mode = ((mode & R_OK ? 4 : 0)
  155:             + (mode & W_OK ? 2 : 0)
  156:             + (mode & X_OK ? 1 : 0));
  157: 
  158:   if (mode == 0)
  159:     return 0;                   /* The file exists.  */
  160: 
  161:   /* Convert the file's permission bits to traditional form.  */
  162:   if (S_IRUSR == (4 << 6) && S_IWUSR == (2 << 6) && S_IXUSR == (1 << 6)
  163:       && S_IRGRP == (4 << 3) && S_IWGRP == (2 << 3) && S_IXGRP == (1 << 3)
  164:       && S_IROTH == (4 << 0) && S_IWOTH == (2 << 0) && S_IXOTH == (1 << 0))
  165:     granted = stats.st_mode;
  166:   else
  167:     granted = ((stats.st_mode & S_IRUSR ? 4 << 6 : 0)
  168:                + (stats.st_mode & S_IWUSR ? 2 << 6 : 0)
  169:                + (stats.st_mode & S_IXUSR ? 1 << 6 : 0)
  170:                + (stats.st_mode & S_IRGRP ? 4 << 3 : 0)
  171:                + (stats.st_mode & S_IWGRP ? 2 << 3 : 0)
  172:                + (stats.st_mode & S_IXGRP ? 1 << 3 : 0)
  173:                + (stats.st_mode & S_IROTH ? 4 << 0 : 0)
  174:                + (stats.st_mode & S_IWOTH ? 2 << 0 : 0)
  175:                + (stats.st_mode & S_IXOTH ? 1 << 0 : 0));
  176: 
  177:   if (euid == stats.st_uid)
  178:     granted >>= 6;
  179:   else if (egid == stats.st_gid || group_member (stats.st_gid))
  180:     granted >>= 3;
  181: 
  182:   if ((mode & ~granted) == 0)
  183:     return 0;
  184:   __set_errno (EACCESS);
  185:   return -1;
  186: 
  187: # endif
  188: #endif
  189: }
  190: #undef euidaccess
  191: #ifdef weak_alias
  192: weak_alias (__euidaccess, euidaccess)
  193: #endif
  194: ^L
  195: #ifdef TEST
  196: # include <error.h>
  197: # include <stdio.h>
  198: # include <stdlib.h>
  199: 
  200: char *program_name;
  201: 
  202: int
  203: main (int argc, char **argv)
  204: {
  205:   char *file;
  206:   int mode;
  207:   int err;
  208: 
  209:   program_name = argv[0];
  210:   if (argc < 3)
  211:     abort ();
  212:   file = argv[1];
  213:   mode = atoi (argv[2]);
  214: 
  215:   err = euidaccess (file, mode);
  216:   printf ("%d\n", err);
  217:   if (err != 0)
  218:     error (0, errno, "%s", file);
  219:   exit (0);
  220: }
  221: #endif
Syntax (Markdown)