14
14
#define GROUP 3
15
15
#define OTHER 0
16
16
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
+
17
25
/* ingroupset -- determine whether gid lies in the user's set of groups */
18
26
static Boolean ingroupset (gidset_t gid ) {
19
- #ifdef NGROUPS
20
27
int i ;
21
28
static int ngroups ;
22
- static gidset_t gidset [ NGROUPS ] ;
29
+ static gidset_t * gidset ;
23
30
static Boolean initialized = FALSE;
24
31
if (!initialized ) {
25
32
initialized = TRUE;
26
- ngroups = getgroups (NGROUPS , gidset );
33
+ ngroups = getgroups (0 , gidset );
34
+ gidset = ealloc (ngroups * sizeof (gidset_t ));
35
+ getgroups (ngroups , gidset );
27
36
}
28
37
for (i = 0 ; i < ngroups ; i ++ )
29
38
if (gid == gidset [i ])
30
39
return TRUE;
31
- #endif
32
40
return FALSE;
33
41
}
34
42
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 ;
37
45
static gidset_t uid , gid ;
38
46
static Boolean initialized = FALSE;
39
47
if (perm == 0 )
@@ -51,21 +59,22 @@ static int testperm(struct stat *stat, int perm) {
51
59
: ((gid == stat -> st_gid || ingroupset (stat -> st_gid ))
52
60
? GROUP
53
61
: OTHER )));
54
- return (stat -> st_mode & mask ) ? 0 : EACCES ;
62
+ return (stat -> st_mode & mask ) == mask ? 0 : EACCES ;
55
63
}
56
64
57
- static int testfile (char * path , int perm , unsigned int type ) {
65
+ static int testfile (char * path , unsigned int perm , unsigned int type ) {
58
66
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
+ }
69
78
return testperm (& st , perm );
70
79
}
71
80
@@ -97,8 +106,9 @@ static char *pathcat(char *prefix, char *suffix) {
97
106
}
98
107
99
108
PRIM (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;
102
112
char * suffix = NULL ;
103
113
List * lp ;
104
114
const char * const usage = "access [-n name] [-1e] [-rwx] [-fdcblsp] path ..." ;
@@ -109,23 +119,17 @@ PRIM(access) {
109
119
switch (c ) {
110
120
case 'n' : suffix = getstr (esoptarg ()); break ;
111
121
case '1' : first = TRUE; break ;
112
- case 'e' : exception = TRUE; break ;
122
+ case 'e' : throws = TRUE; break ;
113
123
case 'r' : perm |= READ ; break ;
114
124
case 'w' : perm |= WRITE ; break ;
115
125
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 ;
129
133
default :
130
134
esoptend ();
131
135
fail ("$&access" , "access -%c is not supported on this system" , c );
@@ -153,11 +157,11 @@ PRIM(access) {
153
157
} else if (error != ENOENT )
154
158
estatus = error ;
155
159
} else
156
- lp = mklist (mkstr (error == 0 ? "0" : esstrerror (error )),
160
+ lp = mklist (mkstr (error == 0 ? "0" : gcdup ( esstrerror (error ) )),
157
161
lp );
158
162
}
159
163
160
- if (first && exception ) {
164
+ if (first && throws ) {
161
165
gcenable ();
162
166
if (suffix )
163
167
fail ("$&access" , "%s: %s" , suffix , esstrerror (estatus ));
@@ -176,6 +180,6 @@ extern Dict *initprims_access(Dict *primdict) {
176
180
}
177
181
178
182
extern char * checkexecutable (char * file ) {
179
- int err = testfile (file , EXEC , S_IFREG );
183
+ int err = testfile (file , EXEC , IFREG );
180
184
return err == 0 ? NULL : esstrerror (err );
181
185
}
0 commit comments