4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Implementation of the Posix access() function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This program and the accompanying materials are licensed and made available under
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the terms and conditions of the BSD License that accompanies this distribution.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync http://opensource.org/licenses/bsd-license.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <LibConfig.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <sys/EfiCdefs.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <ctype.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <errno.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <sys/stat.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <string.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <unistd.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <sys/syslimits.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** Save some typing later on. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define GOOD_MODE (F_OK | X_OK | W_OK | R_OK)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** Determine accessibility of a file.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The access() function checks the file, named by the pathname pointed to by
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the Path argument, for accessibility according to the bit pattern contained
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync in Mode.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The value of Mode is either the bitwise-inclusive OR of the access
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync permissions to be checked (R_OK, W_OK, X_OK) or the existence test (F_OK).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If Path ends in '/' or '\\', the target must be a directory, otherwise it doesn't matter.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync A file is executable if it is NOT a directory and it ends in ".efi".
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Path Path or name of the file to be checked.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Mode Access permissions to check for.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 0 Successful completion.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval -1 File is not accessible with the given Mode. The error condition
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync is indicated by errno. Values of errno specific to the access
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync function include: EACCES, ENOENT, ENOTDIR, ENAMETOOLONG
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncint
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncaccess(
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char *Path,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int Mode
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync struct stat FileStat;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync int retval = -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync size_t PLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t WantDir;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync uint32_t DirMatch;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if((Path == NULL) || ((Mode & ~GOOD_MODE) != 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync errno = EINVAL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PLength = strlen(Path);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if(PLength > PATH_MAX) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync errno = ENAMETOOLONG;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync retval = stat(Path, &FileStat);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if(retval == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Path exists. FileStat now holds valid information. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WantDir = isDirSep(Path[PLength - 1]); // Does Path end in '/' or '\\' ?
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirMatch = (! WantDir && (! S_ISDIR(FileStat.st_mode)));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Test each permission individually. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if(Mode == F_OK) { /* Existence test. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if(DirMatch) { /* This is a directory or file as desired. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync retval = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Indicate why we failed the test. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync errno = (WantDir) ? ENOTDIR : EISDIR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break; /* F_OK does not combine with any other tests. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if(Mode & R_OK) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if((FileStat.st_mode & READ_PERMS) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* No read permissions.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync For UEFI, everything should have READ permissions.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync errno = EDOOFUS; /* Programming Error. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if(Mode & W_OK) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if((FileStat.st_mode & WRITE_PERMS) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* No write permissions. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync errno = EACCES; /* Writing is not OK. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if(Mode & X_OK) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* In EDK II, executable files end in ".efi" */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if(strcmp(&Path[PLength-4], ".efi") != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* File is not an executable. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync errno = EACCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync retval = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while(FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* File or path does not exist. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync errno = ENOENT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return retval;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}