/*********************************************************************** * * * This software is part of the ast package * * Copyright (c) 1985-2009 AT&T Intellectual Property * * and is licensed under the * * Common Public License, Version 1.0 * * by AT&T Intellectual Property * * * * A copy of the License is available at * * http://www.opensource.org/licenses/cpl1.0.txt * * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * * * * Information and Software Systems Research * * AT&T Research * * Florham Park NJ * * * * Glenn Fowler * * David Korn * * Phong Vo * * * ***********************************************************************/ #pragma prototyped /* * access() euid/egid implementation */ #include #include #include #include "FEATURE/eaccess" #if _lib_eaccess NoN(eaccess) #else #if defined(__EXPORT__) #define extern __EXPORT__ #endif extern int eaccess(const char* path, register int flags) { #ifdef EFF_ONLY_OK return access(path, flags|EFF_ONLY_OK); #else #if _lib_euidaccess return euidaccess(path, flags); #else register int mode; struct stat st; static int init; static uid_t ruid; static uid_t euid; static gid_t rgid; static gid_t egid; if (!init) { ruid = getuid(); euid = geteuid(); rgid = getgid(); egid = getegid(); init = (ruid == euid && rgid == egid) ? 1 : -1; } if (init > 0 || flags == F_OK) return access(path, flags); if (stat(path, &st)) return -1; mode = 0; if (euid == 0) { if (!S_ISREG(st.st_mode) || !(flags & X_OK) || (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) return 0; goto nope; } else if (euid == st.st_uid) { if (flags & R_OK) mode |= S_IRUSR; if (flags & W_OK) mode |= S_IWUSR; if (flags & X_OK) mode |= S_IXUSR; } else if (egid == st.st_gid) { #if _lib_getgroups setgroup: #endif if (flags & R_OK) mode |= S_IRGRP; if (flags & W_OK) mode |= S_IWGRP; if (flags & X_OK) mode |= S_IXGRP; } else { #if _lib_getgroups register int n; static int ngroups = -2; static gid_t* groups; if (ngroups == -2) { if ((ngroups = getgroups(0, (gid_t*)0)) <= 0) ngroups = NGROUPS_MAX; if (!(groups = newof(0, gid_t, ngroups + 1, 0))) ngroups = -1; else ngroups = getgroups(ngroups, groups); } n = ngroups; while (--n >= 0) if (groups[n] == st.st_gid) goto setgroup; #endif if (flags & R_OK) mode |= S_IROTH; if (flags & W_OK) mode |= S_IWOTH; if (flags & X_OK) mode |= S_IXOTH; } if ((st.st_mode & mode) == mode) return 0; nope: errno = EACCES; return -1; #endif #endif } #endif