1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: canaccess.c 769 2007-10-24 00:15:40Z hubert@u.washington.edu $";
6 * ========================================================================
7 * Copyright 2006-2007 University of Washington
8 * Copyright 2013-2014 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
22 #include "../charconv/utf8.h"
23 #include "../charconv/filesys.h"
24 #include "canaccess.h"
32 #define ACCESS_IN_CWD(F,M) (can_access((F), (M)))
38 #define ACCESS_IN_CWD(F,M) (-1)
47 * Check if we can access a file in a given way
49 * Args: file -- The file to check
50 * mode -- The mode ala the access() system call, see ACCESS_EXISTS
51 * and friends in alpine.h.
53 * Result: returns 0 if the user can access the file according to the mode,
54 * -1 if he can't (and errno is set).
59 can_access(char *file
, int mode
)
65 * NOTE: The WinNT access call returns that every directory is readable and
66 * writable. We actually want to know if the write is going to fail, so we
67 * try it. We don't read directories in Windows so we skip implementing that.
69 if(mode
& WRITE_ACCESS
&& file
&& !our_stat(file
, &buf
) && (buf
.st_mode
& S_IFMT
) == S_IFDIR
){
75 * We'd like to just call temp_nam here, since it creates a file
76 * and does what we want. However, temp_nam calls us!
78 if((testname
= malloc(MAXPATH
* sizeof(char)))){
79 strncpy(testname
, file
, MAXPATH
-1);
80 testname
[MAXPATH
-1] = '\0';
81 if(testname
[0] && testname
[(l
=strlen(testname
))-1] != '\\' &&
84 strncat(testname
, "\\", MAXPATH
-strlen(testname
)-1);
85 testname
[MAXPATH
-1] = '\0';
89 strncat(testname
, "caXXXXXX", MAXPATH
-strlen(testname
)-1) && mktemp(testname
)){
90 if((fd
= our_open(testname
, O_CREAT
|O_EXCL
|O_WRONLY
|O_BINARY
, 0600)) >= 0){
94 /* success, drop through to access call */
98 /* can't write in the directory */
108 if(mode
& EXECUTE_ACCESS
) /* Windows access has no execute mode */
109 mode
&= ~EXECUTE_ACCESS
; /* and crashes because of it */
112 return(our_access(file
, mode
));
116 /*----------------------------------------------------------------------
117 Check if we can access a file in a given way in the given path
119 Args: path -- The path to look for "file" in
120 file -- The file to check
121 mode -- The mode ala the access() system call, see ACCESS_EXISTS
122 and friends in alpine.h.
124 Result: returns 0 if the user can access the file according to the mode,
125 -1 if he can't (and errno is set).
128 can_access_in_path(char *path
, char *file
, int mode
)
133 if(!path
|| !*path
|| is_rooted_path(file
)){
134 rv
= can_access(file
, mode
);
136 else if(is_homedir_path(file
)){
137 strncpy(tmp
, file
, sizeof(tmp
));
138 tmp
[sizeof(tmp
)-1] = '\0';
139 rv
= fnexpand(tmp
, sizeof(tmp
)) ? can_access(tmp
, mode
) : -1;
141 else if((rv
= ACCESS_IN_CWD(file
,mode
)) < 0){
142 char path_copy
[MAXPATH
+ 1], *p
, *t
;
144 if(strlen(path
) < MAXPATH
){
145 strncpy(path_copy
, path
, sizeof(path_copy
));
146 path_copy
[sizeof(path_copy
)-1] = '\0';
148 for(p
= path_copy
; p
&& *p
; p
= t
){
149 if((t
= strchr(p
, PATH_SEP
)) != NULL
)
152 snprintf(tmp
, sizeof(tmp
), "%s%c%s", p
, FILE_SEP
, file
);
153 if((rv
= can_access(tmp
, mode
)) == 0)