1414#define GROUP 3
1515#define OTHER 0
1616
17+ #define IFREG 1
18+ #define IFDIR 2
19+ #define IFCHR 3
20+ #define IFBLK 4
21+ #define IFLNK 5
22+ #define IFSOCK 6
23+ #define IFIFO 7
24+
1725/* ingroupset -- determine whether gid lies in the user's set of groups */
1826static Boolean ingroupset (gidset_t gid ) {
19- #ifdef NGROUPS
2027 int i ;
2128 static int ngroups ;
22- static gidset_t gidset [ NGROUPS ] ;
29+ static gidset_t * gidset ;
2330 static Boolean initialized = FALSE;
2431 if (!initialized ) {
2532 initialized = TRUE;
26- ngroups = getgroups (NGROUPS , gidset );
33+ ngroups = getgroups (0 , gidset );
34+ gidset = ealloc (ngroups * sizeof (gidset_t ));
35+ getgroups (ngroups , gidset );
2736 }
2837 for (i = 0 ; i < ngroups ; i ++ )
2938 if (gid == gidset [i ])
3039 return TRUE;
31- #endif
3240 return FALSE;
3341}
3442
35- static int testperm (struct stat * stat , int perm ) {
36- int mask ;
43+ static int testperm (struct stat * stat , unsigned int perm ) {
44+ unsigned int mask ;
3745 static gidset_t uid , gid ;
3846 static Boolean initialized = FALSE;
3947 if (perm == 0 )
@@ -51,21 +59,22 @@ static int testperm(struct stat *stat, int perm) {
5159 : ((gid == stat -> st_gid || ingroupset (stat -> st_gid ))
5260 ? GROUP
5361 : OTHER )));
54- return (stat -> st_mode & mask ) ? 0 : EACCES ;
62+ return (stat -> st_mode & mask ) == mask ? 0 : EACCES ;
5563}
5664
57- static int testfile (char * path , int perm , unsigned int type ) {
65+ static int testfile (char * path , unsigned int perm , unsigned int type ) {
5866 struct stat st ;
59- #ifdef S_IFLNK
60- if (type == S_IFLNK ) {
61- if (lstat (path , & st ) == -1 )
62- return errno ;
63- } else
64- #endif
65- if (stat (path , & st ) == -1 )
66- return errno ;
67- if (type != 0 && (st .st_mode & S_IFMT ) != type )
68- return EACCES ; /* what is an appropriate return value? */
67+ if ((type == IFLNK ? lstat (path , & st ) : stat (path , & st )) == -1 )
68+ return errno ;
69+ /* is EACCES the right return value? */
70+ switch (type ) {
71+ case IFREG : if (!S_ISREG (st .st_mode )) return EACCES ; break ;
72+ case IFDIR : if (!S_ISDIR (st .st_mode )) return EACCES ; break ;
73+ case IFBLK : if (!S_ISBLK (st .st_mode )) return EACCES ; break ;
74+ case IFLNK : if (!S_ISLNK (st .st_mode )) return EACCES ; break ;
75+ case IFSOCK : if (!S_ISSOCK (st .st_mode )) return EACCES ; break ;
76+ case IFIFO : if (!S_ISFIFO (st .st_mode )) return EACCES ; break ;
77+ }
6978 return testperm (& st , perm );
7079}
7180
@@ -97,8 +106,9 @@ static char *pathcat(char *prefix, char *suffix) {
97106}
98107
99108PRIM (access ) {
100- int c , perm = 0 , type = 0 , estatus = ENOENT ;
101- Boolean first = FALSE, exception = FALSE;
109+ int c , estatus = ENOENT ;
110+ unsigned int perm = 0 , type = 0 ;
111+ Boolean first = FALSE, throws = FALSE;
102112 char * suffix = NULL ;
103113 List * lp ;
104114 const char * const usage = "access [-n name] [-1e] [-rwx] [-fdcblsp] path ..." ;
@@ -109,23 +119,17 @@ PRIM(access) {
109119 switch (c ) {
110120 case 'n' : suffix = getstr (esoptarg ()); break ;
111121 case '1' : first = TRUE; break ;
112- case 'e' : exception = TRUE; break ;
122+ case 'e' : throws = TRUE; break ;
113123 case 'r' : perm |= READ ; break ;
114124 case 'w' : perm |= WRITE ; break ;
115125 case 'x' : perm |= EXEC ; break ;
116- case 'f' : type = S_IFREG ; break ;
117- case 'd' : type = S_IFDIR ; break ;
118- case 'c' : type = S_IFCHR ; break ;
119- case 'b' : type = S_IFBLK ; break ;
120- #ifdef S_IFLNK
121- case 'l' : type = S_IFLNK ; break ;
122- #endif
123- #ifdef S_IFSOCK
124- case 's' : type = S_IFSOCK ; break ;
125- #endif
126- #ifdef S_IFIFO
127- case 'p' : type = S_IFIFO ; break ;
128- #endif
126+ case 'f' : type = IFREG ; break ;
127+ case 'd' : type = IFDIR ; break ;
128+ case 'c' : type = IFCHR ; break ;
129+ case 'b' : type = IFBLK ; break ;
130+ case 'l' : type = IFLNK ; break ;
131+ case 's' : type = IFSOCK ; break ;
132+ case 'p' : type = IFIFO ; break ;
129133 default :
130134 esoptend ();
131135 fail ("$&access" , "access -%c is not supported on this system" , c );
@@ -153,11 +157,11 @@ PRIM(access) {
153157 } else if (error != ENOENT )
154158 estatus = error ;
155159 } else
156- lp = mklist (mkstr (error == 0 ? "0" : esstrerror (error )),
160+ lp = mklist (mkstr (error == 0 ? "0" : gcdup ( esstrerror (error ) )),
157161 lp );
158162 }
159163
160- if (first && exception ) {
164+ if (first && throws ) {
161165 gcenable ();
162166 if (suffix )
163167 fail ("$&access" , "%s: %s" , suffix , esstrerror (estatus ));
@@ -176,6 +180,6 @@ extern Dict *initprims_access(Dict *primdict) {
176180}
177181
178182extern char * checkexecutable (char * file ) {
179- int err = testfile (file , EXEC , S_IFREG );
183+ int err = testfile (file , EXEC , IFREG );
180184 return err == 0 ? NULL : esstrerror (err );
181185}
0 commit comments