1 | /** @file
|
---|
2 | Implementation of the Posix access() function.
|
---|
3 |
|
---|
4 | Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
---|
5 | This program and the accompanying materials are licensed and made available under
|
---|
6 | the terms and conditions of the BSD License that accompanies this distribution.
|
---|
7 | The full text of the license may be found at
|
---|
8 | http://opensource.org/licenses/bsd-license.
|
---|
9 |
|
---|
10 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
---|
11 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
---|
12 | **/
|
---|
13 | #include <LibConfig.h>
|
---|
14 | #include <sys/EfiCdefs.h>
|
---|
15 |
|
---|
16 | #include <ctype.h>
|
---|
17 | #include <errno.h>
|
---|
18 | #include <sys/stat.h>
|
---|
19 | #include <string.h>
|
---|
20 | #include <unistd.h>
|
---|
21 | #include <sys/syslimits.h>
|
---|
22 |
|
---|
23 | /** Save some typing later on. */
|
---|
24 | #define GOOD_MODE (F_OK | X_OK | W_OK | R_OK)
|
---|
25 |
|
---|
26 | /** Determine accessibility of a file.
|
---|
27 | The access() function checks the file, named by the pathname pointed to by
|
---|
28 | the Path argument, for accessibility according to the bit pattern contained
|
---|
29 | in Mode.
|
---|
30 |
|
---|
31 | The value of Mode is either the bitwise-inclusive OR of the access
|
---|
32 | permissions to be checked (R_OK, W_OK, X_OK) or the existence test (F_OK).
|
---|
33 |
|
---|
34 | If Path ends in '/' or '\\', the target must be a directory, otherwise it doesn't matter.
|
---|
35 | A file is executable if it is NOT a directory and it ends in ".efi".
|
---|
36 |
|
---|
37 | @param[in] Path Path or name of the file to be checked.
|
---|
38 | @param[in] Mode Access permissions to check for.
|
---|
39 |
|
---|
40 | @retval 0 Successful completion.
|
---|
41 | @retval -1 File is not accessible with the given Mode. The error condition
|
---|
42 | is indicated by errno. Values of errno specific to the access
|
---|
43 | function include: EACCES, ENOENT, ENOTDIR, ENAMETOOLONG
|
---|
44 | **/
|
---|
45 | int
|
---|
46 | access(
|
---|
47 | const char *Path,
|
---|
48 | int Mode
|
---|
49 | )
|
---|
50 | {
|
---|
51 | struct stat FileStat;
|
---|
52 | int retval = -1;
|
---|
53 | size_t PLength;
|
---|
54 | uint32_t WantDir;
|
---|
55 | uint32_t DirMatch;
|
---|
56 |
|
---|
57 | if((Path == NULL) || ((Mode & ~GOOD_MODE) != 0)) {
|
---|
58 | errno = EINVAL;
|
---|
59 | }
|
---|
60 | else {
|
---|
61 | PLength = strlen(Path);
|
---|
62 | if(PLength > PATH_MAX) {
|
---|
63 | errno = ENAMETOOLONG;
|
---|
64 | }
|
---|
65 | else {
|
---|
66 | retval = stat(Path, &FileStat);
|
---|
67 | if(retval == 0) {
|
---|
68 | /* Path exists. FileStat now holds valid information. */
|
---|
69 | WantDir = isDirSep(Path[PLength - 1]); // Does Path end in '/' or '\\' ?
|
---|
70 | DirMatch = (! WantDir && (! S_ISDIR(FileStat.st_mode)));
|
---|
71 |
|
---|
72 | /* Test each permission individually. */
|
---|
73 | do {
|
---|
74 | if(Mode == F_OK) { /* Existence test. */
|
---|
75 | if(DirMatch) { /* This is a directory or file as desired. */
|
---|
76 | retval = 0;
|
---|
77 | }
|
---|
78 | else {
|
---|
79 | /* Indicate why we failed the test. */
|
---|
80 | errno = (WantDir) ? ENOTDIR : EISDIR;
|
---|
81 | }
|
---|
82 | break; /* F_OK does not combine with any other tests. */
|
---|
83 | }
|
---|
84 | if(Mode & R_OK) {
|
---|
85 | if((FileStat.st_mode & READ_PERMS) == 0) {
|
---|
86 | /* No read permissions.
|
---|
87 | For UEFI, everything should have READ permissions.
|
---|
88 | */
|
---|
89 | errno = EDOOFUS; /* Programming Error. */
|
---|
90 | break;
|
---|
91 | }
|
---|
92 | }
|
---|
93 | if(Mode & W_OK) {
|
---|
94 | if((FileStat.st_mode & WRITE_PERMS) == 0) {
|
---|
95 | /* No write permissions. */
|
---|
96 | errno = EACCES; /* Writing is not OK. */
|
---|
97 | break;
|
---|
98 | }
|
---|
99 | }
|
---|
100 | if(Mode & X_OK) {
|
---|
101 | /* In EDK II, executable files end in ".efi" */
|
---|
102 | if(strcmp(&Path[PLength-4], ".efi") != 0) {
|
---|
103 | /* File is not an executable. */
|
---|
104 | errno = EACCES;
|
---|
105 | break;
|
---|
106 | }
|
---|
107 | }
|
---|
108 | retval = 0;
|
---|
109 | } while(FALSE);
|
---|
110 | }
|
---|
111 | else {
|
---|
112 | /* File or path does not exist. */
|
---|
113 | errno = ENOENT;
|
---|
114 | }
|
---|
115 | }
|
---|
116 | }
|
---|
117 | return retval;
|
---|
118 | }
|
---|