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