summaryrefslogtreecommitdiff
path: root/usr/src/lib/libast/common/comp/eaccess.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libast/common/comp/eaccess.c')
-rw-r--r--usr/src/lib/libast/common/comp/eaccess.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/usr/src/lib/libast/common/comp/eaccess.c b/usr/src/lib/libast/common/comp/eaccess.c
new file mode 100644
index 0000000000..3604fe835f
--- /dev/null
+++ b/usr/src/lib/libast/common/comp/eaccess.c
@@ -0,0 +1,139 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1985-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* 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 <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* Phong Vo <kpv@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * access() euid/egid implementation
+ */
+
+#include <ast.h>
+#include <errno.h>
+#include <ls.h>
+
+#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