* Implement a different way to delete a password from the cache.
[alpine.git] / pith / osdep / canaccess.c
blob853e5b4c5df6bda558e6bdadcc85b6f8d48bb4ce
1 /*
2 * ========================================================================
3 * Copyright 2013-2022 Eduardo Chappa
4 * Copyright 2006-2007 University of Washington
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
15 #include <system.h>
16 #include "bldpath.h"
17 #include "fnexpand.h"
18 #include "../charconv/utf8.h"
19 #include "../charconv/filesys.h"
20 #include "canaccess.h"
24 * Useful definitions
26 #ifdef _WINDOWS
28 #define ACCESS_IN_CWD(F,M) (can_access((F), (M)))
29 #define PATH_SEP ';'
30 #define FILE_SEP '\\'
32 #else /* UNIX */
34 #define ACCESS_IN_CWD(F,M) (-1)
35 #define PATH_SEP ':'
36 #define FILE_SEP '/'
38 #endif /* UNIX */
43 * Check if we can access a file in a given way
45 * Args: file -- The file to check
46 * mode -- The mode ala the access() system call, see ACCESS_EXISTS
47 * and friends in alpine.h.
49 * Result: returns 0 if the user can access the file according to the mode,
50 * -1 if he can't (and errno is set).
54 int
55 can_access(char *file, int mode)
57 #ifdef _WINDOWS
58 struct stat buf;
61 * NOTE: The WinNT access call returns that every directory is readable and
62 * writable. We actually want to know if the write is going to fail, so we
63 * try it. We don't read directories in Windows so we skip implementing that.
65 if(mode & WRITE_ACCESS && file && !our_stat(file, &buf) && (buf.st_mode & S_IFMT) == S_IFDIR){
66 char *testname;
67 int fd;
68 size_t l = 0;
71 * We'd like to just call temp_nam here, since it creates a file
72 * and does what we want. However, temp_nam calls us!
74 if((testname = malloc(MAXPATH * sizeof(char)))){
75 strncpy(testname, file, MAXPATH-1);
76 testname[MAXPATH-1] = '\0';
77 if(testname[0] && testname[(l=strlen(testname))-1] != '\\' &&
78 l+1 < MAXPATH){
79 l++;
80 strncat(testname, "\\", MAXPATH-strlen(testname)-1);
81 testname[MAXPATH-1] = '\0';
84 if(l+8 < MAXPATH &&
85 strncat(testname, "caXXXXXX", MAXPATH-strlen(testname)-1) && mktemp(testname)){
86 if((fd = our_open(testname, O_CREAT|O_EXCL|O_WRONLY|O_BINARY, 0600)) >= 0){
87 (void)close(fd);
88 our_unlink(testname);
89 free(testname);
90 /* success, drop through to access call */
92 else{
93 free(testname);
94 /* can't write in the directory */
95 return(-1);
98 else{
99 free(testname);
100 return(-1);
104 if(mode & EXECUTE_ACCESS) /* Windows access has no execute mode */
105 mode &= ~EXECUTE_ACCESS; /* and crashes because of it */
106 #endif /* WINDOWS */
108 return(our_access(file, mode));
112 /*----------------------------------------------------------------------
113 Check if we can access a file in a given way in the given path
115 Args: path -- The path to look for "file" in
116 file -- The file to check
117 mode -- The mode ala the access() system call, see ACCESS_EXISTS
118 and friends in alpine.h.
120 Result: returns 0 if the user can access the file according to the mode,
121 -1 if he can't (and errno is set).
122 ----*/
124 can_access_in_path(char *path, char *file, int mode)
126 char tmp[MAXPATH];
127 int rv = -1;
129 if(!path || !*path || is_rooted_path(file)){
130 rv = can_access(file, mode);
132 else if(is_homedir_path(file)){
133 strncpy(tmp, file, sizeof(tmp));
134 tmp[sizeof(tmp)-1] = '\0';
135 rv = fnexpand(tmp, sizeof(tmp)) ? can_access(tmp, mode) : -1;
137 else if((rv = ACCESS_IN_CWD(file,mode)) < 0){
138 char path_copy[MAXPATH + 1], *p, *t;
140 if(strlen(path) < MAXPATH){
141 strncpy(path_copy, path, sizeof(path_copy));
142 path_copy[sizeof(path_copy)-1] = '\0';
144 for(p = path_copy; p && *p; p = t){
145 if((t = strchr(p, PATH_SEP)) != NULL)
146 *t++ = '\0';
148 snprintf(tmp, sizeof(tmp), "%s%c%s", p, FILE_SEP, file);
149 if((rv = can_access(tmp, mode)) == 0)
150 break;
155 return(rv);