From 094ca96844842928810f14844413109fc6cdd890 Mon Sep 17 00:00:00 2001 From: Eduardo Chappa Date: Sun, 3 Feb 2013 00:59:38 -0700 Subject: Initial Alpine Version --- pith/osdep/canaccess.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 pith/osdep/canaccess.c (limited to 'pith/osdep/canaccess.c') diff --git a/pith/osdep/canaccess.c b/pith/osdep/canaccess.c new file mode 100644 index 00000000..4d79c407 --- /dev/null +++ b/pith/osdep/canaccess.c @@ -0,0 +1,160 @@ +#if !defined(lint) && !defined(DOS) +static char rcsid[] = "$Id: canaccess.c 769 2007-10-24 00:15:40Z hubert@u.washington.edu $"; +#endif + +/* + * ======================================================================== + * Copyright 2006-2007 University of Washington + * Copyright 2013 Eduardo Chappa + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * ======================================================================== + */ + +#include +#include "bldpath.h" +#include "fnexpand.h" +#include "../charconv/utf8.h" +#include "../charconv/filesys.h" +#include "canaccess.h" + + +/* + * Useful definitions + */ +#ifdef _WINDOWS + +#define ACCESS_IN_CWD(F,M) (can_access((F), (M))) +#define PATH_SEP ';' +#define FILE_SEP '\\' + +#else /* UNIX */ + +#define ACCESS_IN_CWD(F,M) (-1) +#define PATH_SEP ':' +#define FILE_SEP '/' + +#endif /* UNIX */ + + + +/* + * Check if we can access a file in a given way + * + * Args: file -- The file to check + * mode -- The mode ala the access() system call, see ACCESS_EXISTS + * and friends in alpine.h. + * + * Result: returns 0 if the user can access the file according to the mode, + * -1 if he can't (and errno is set). + * + * + */ +int +can_access(char *file, int mode) +{ +#ifdef _WINDOWS + struct stat buf; + + /* + * NOTE: The WinNT access call returns that every directory is readable and + * writable. We actually want to know if the write is going to fail, so we + * try it. We don't read directories in Windows so we skip implementing that. + */ + if(mode & WRITE_ACCESS && file && !our_stat(file, &buf) && (buf.st_mode & S_IFMT) == S_IFDIR){ + char *testname; + int fd; + size_t l = 0; + + /* + * We'd like to just call temp_nam here, since it creates a file + * and does what we want. However, temp_nam calls us! + */ + if((testname = malloc(MAXPATH * sizeof(char)))){ + strncpy(testname, file, MAXPATH-1); + testname[MAXPATH-1] = '\0'; + if(testname[0] && testname[(l=strlen(testname))-1] != '\\' && + l+1 < MAXPATH){ + l++; + strncat(testname, "\\", MAXPATH-strlen(testname)-1); + testname[MAXPATH-1] = '\0'; + } + + if(l+8 < MAXPATH && + strncat(testname, "caXXXXXX", MAXPATH-strlen(testname)-1) && mktemp(testname)){ + if((fd = our_open(testname, O_CREAT|O_EXCL|O_WRONLY|O_BINARY, 0600)) >= 0){ + (void)close(fd); + our_unlink(testname); + free(testname); + /* success, drop through to access call */ + } + else{ + free(testname); + /* can't write in the directory */ + return(-1); + } + } + else{ + free(testname); + return(-1); + } + } + } + if(mode & EXECUTE_ACCESS) /* Windows access has no execute mode */ + mode &= ~EXECUTE_ACCESS; /* and crashes because of it */ +#endif /* WINDOWS */ + + return(our_access(file, mode)); +} + + +/*---------------------------------------------------------------------- + Check if we can access a file in a given way in the given path + + Args: path -- The path to look for "file" in + file -- The file to check + mode -- The mode ala the access() system call, see ACCESS_EXISTS + and friends in alpine.h. + + Result: returns 0 if the user can access the file according to the mode, + -1 if he can't (and errno is set). + ----*/ +int +can_access_in_path(char *path, char *file, int mode) +{ + char tmp[MAXPATH]; + int rv = -1; + + if(!path || !*path || is_rooted_path(file)){ + rv = can_access(file, mode); + } + else if(is_homedir_path(file)){ + strncpy(tmp, file, sizeof(tmp)); + tmp[sizeof(tmp)-1] = '\0'; + rv = fnexpand(tmp, sizeof(tmp)) ? can_access(tmp, mode) : -1; + } + else if((rv = ACCESS_IN_CWD(file,mode)) < 0){ + char path_copy[MAXPATH + 1], *p, *t; + + if(strlen(path) < MAXPATH){ + strncpy(path_copy, path, sizeof(path_copy)); + path_copy[sizeof(path_copy)-1] = '\0'; + + for(p = path_copy; p && *p; p = t){ + if((t = strchr(p, PATH_SEP)) != NULL) + *t++ = '\0'; + + snprintf(tmp, sizeof(tmp), "%s%c%s", p, FILE_SEP, file); + if((rv = can_access(tmp, mode)) == 0) + break; + } + } + } + + return(rv); +} -- cgit v1.2.3-54-g00ecf