1 /* euidaccess -- check if effective user id can access file
3 Copyright (C) 1990, 1991, 1995, 1998, 2000, 2003, 2004 Free
4 Software Foundation, Inc.
6 This file is part of the GNU C Library.
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)
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 /* Written by David MacKenzie and Torbjorn Granlund.
23 Adapted for GNU C library by Roland McGrath. */
30 # include "euidaccess.h"
33 #include <sys/types.h>
36 #if HAVE_UNISTD_H || defined _LIBC
44 #ifndef _POSIX_VERSION
53 # define __set_errno(val) errno = (val)
56 #if defined EACCES && !defined EACCESS
57 # define EACCESS EACCES
70 # define access __access
71 # define getuid __getuid
72 # define getgid __getgid
73 # define geteuid __geteuid
74 # define getegid __getegid
75 # define group_member __group_member
76 # define euidaccess __euidaccess
82 # include "group-member.h"
83 # include "stat-macros.h"
87 /* Return 0 if the user has permission of type MODE on file PATH;
88 otherwise, return -1 and set `errno'.
89 Like access, except that it uses the effective user and group
90 id's instead of the real ones, and it does not always check for read-only
91 file system, text busy, etc. */
94 euidaccess (const char *path, int mode)
96 #if defined EFF_ONLY_OK
97 return access (path, mode | EFF_ONLY_OK);
98 #elif defined ACC_SELF
99 return accessx (path, mode, ACC_SELF);
101 return eaccess (path, mode);
104 uid_t uid = getuid ();
105 gid_t gid = getgid ();
106 uid_t euid = geteuid ();
107 gid_t egid = getegid ();
110 # if HAVE_DECL_SETREGID && PREFER_NONREENTRANT_EUIDACCESS
112 /* Define PREFER_NONREENTRANT_EUIDACCESS if you prefer euidaccess to
113 return the correct result even if this would make it
114 nonreentrant. Define this only if your entire application is
115 safe even if the uid or gid might temporarily change. If your
116 application uses signal handlers or threads it is probably not
120 return stat (path, &stats);
127 setreuid (euid, uid);
129 setregid (egid, gid);
131 result = access (path, mode);
136 setreuid (uid, euid);
138 setregid (gid, egid);
146 /* The following code assumes the traditional Unix model, and is not
147 correct on systems that have ACLs or the like. However, it's
148 better than nothing, and it is reentrant. */
150 unsigned int granted;
151 if (uid == euid && gid == egid)
152 /* If we are not set-uid or set-gid, access does the same. */
153 return access (path, mode);
155 if (stat (path, &stats))
158 /* The super-user can read and write any file, and execute any file
159 that anyone can execute. */
160 if (euid == 0 && ((mode & X_OK) == 0
161 || (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
164 /* Convert the mode to traditional form, clearing any bogus bits. */
165 if (R_OK == 4 && W_OK == 2 && X_OK == 1 && F_OK == 0)
168 mode = ((mode & R_OK ? 4 : 0)
169 + (mode & W_OK ? 2 : 0)
170 + (mode & X_OK ? 1 : 0));
173 return 0; /* The file exists. */
175 /* Convert the file's permission bits to traditional form. */
176 if (S_IRUSR == (4 << 6) && S_IWUSR == (2 << 6) && S_IXUSR == (1 << 6)
177 && S_IRGRP == (4 << 3) && S_IWGRP == (2 << 3) && S_IXGRP == (1 << 3)
178 && S_IROTH == (4 << 0) && S_IWOTH == (2 << 0) && S_IXOTH == (1 << 0))
179 granted = stats.st_mode;
181 granted = ((stats.st_mode & S_IRUSR ? 4 << 6 : 0)
182 + (stats.st_mode & S_IWUSR ? 2 << 6 : 0)
183 + (stats.st_mode & S_IXUSR ? 1 << 6 : 0)
184 + (stats.st_mode & S_IRGRP ? 4 << 3 : 0)
185 + (stats.st_mode & S_IWGRP ? 2 << 3 : 0)
186 + (stats.st_mode & S_IXGRP ? 1 << 3 : 0)
187 + (stats.st_mode & S_IROTH ? 4 << 0 : 0)
188 + (stats.st_mode & S_IWOTH ? 2 << 0 : 0)
189 + (stats.st_mode & S_IXOTH ? 1 << 0 : 0));
191 if (euid == stats.st_uid)
193 else if (egid == stats.st_gid || group_member (stats.st_gid))
196 if ((mode & ~granted) == 0)
198 __set_errno (EACCESS);
206 weak_alias (__euidaccess, euidaccess)
217 main (int argc, char **argv)
223 program_name = argv[0];
227 mode = atoi (argv[2]);
229 err = euidaccess (file, mode);
230 printf ("%d\n", err);
232 error (0, errno, "%s", file);