/* Copyright (C) 2015 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2002 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2000 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include #include #include #include #include #include #include #include #include #include int access(const char *fn, int flags) { int attr; char file_name[FILENAME_MAX]; if (!__solve_symlinks(fn, file_name)) return -1; attr = _chmod(file_name, 0); if (attr == -1) { struct ffblk ff; char fixed_path[FILENAME_MAX]; /* Root directories on some non-local drives (e.g. CD-ROM) might fail `_chmod'. `findfirst' to the rescue. */ _fixpath(file_name, fixed_path); if (fixed_path[1] == ':' && fixed_path[2] == '/' && fixed_path[3] == 0) { char *fp = fixed_path + 3; *fp++ = '*'; *fp++ = '.'; *fp++ = '*'; *fp++ = '\0'; /* Use _lfn_close_handle so we don't lose a handle. */ if (findfirst(fixed_path, &ff, FA_DIREC) == 0) { if (strcmp(ff.lfn_magic, "LFN32") == 0) _lfn_find_close(ff.lfn_handle); return 0; } } /* findfirst() below may be tricked by wildcards so disallow. */ if (strchr(file_name, '*') || strchr(file_name, '?')) { errno = ENOENT; return -1; } /* Devices also fail `_chmod'; some programs won't write to a device unless `access' tells them they are writeable. */ if (findfirst(file_name, &ff, FA_RDONLY | FA_ARCH) == 0 && (ff.ff_attrib & 0x40) == 0x40 && (flags & (X_OK | D_OK)) == 0) { if (strcmp(ff.lfn_magic, "LFN32") == 0) _lfn_find_close(ff.lfn_handle); return 0; } errno = ENOENT; return -1; } if (attr & 0x10) /* directory? */ return 0; /* directories always OK */ if (flags & D_OK) { errno = EACCES; return -1; /* not a directory */ } if ((flags & W_OK) && (attr & 3)) /* read-only, system or hidden */ { errno = EACCES; return -1; /* not writable */ } if (flags & X_OK) { if (!_is_executable(file_name, 0, 0)) { errno = EACCES; return -1; } } return 0; /* everything else is OK */ }