|  | 
|  | 1 | +/******************************************************************************* | 
|  | 2 | + * access() checks whether the calling process can access the file pathname. If | 
|  | 3 | + * pathname is a symbolic link, it is dereferenced. | 
|  | 4 | + * | 
|  | 5 | + * The mode specifies the accessibility check(s) to be performed, and is either | 
|  | 6 | + * the value F_OK, or a mask consisting of the bitwise OR of one or more of R_OK, | 
|  | 7 | + * W_OK, and X_OK. F_OK tests for the existence of the file. R_OK, W_OK, and | 
|  | 8 | + * X_OK test whether the file exists and grants read, write, and execute permis‐ | 
|  | 9 | + * sions, respectively. | 
|  | 10 | + * | 
|  | 11 | + * The check is done using the calling process's real UID and GID, rather than | 
|  | 12 | + * the effective IDs as is done when actually attempting an operation (e.g., | 
|  | 13 | + * open(2)) on the file. Similarly, for the root user, the check uses the set of | 
|  | 14 | + * permitted capabilities rather than the set of effective capabilities; and for | 
|  | 15 | + * non-root users, the check uses an empty set of capabilities. | 
|  | 16 | + ******************************************************************************/ | 
|  | 17 | + | 
|  | 18 | +#include <stdlib.h> | 
|  | 19 | +#include <stdio.h> | 
|  | 20 | +#include <string.h> | 
|  | 21 | +#include <unistd.h> | 
|  | 22 | + | 
|  | 23 | + | 
|  | 24 | +void print_help(char *msg, int rc) | 
|  | 25 | +{ | 
|  | 26 | + if (msg != NULL) fprintf(stderr, "%s\n", msg); | 
|  | 27 | + fprintf(stderr, "my_access -h\n"); | 
|  | 28 | + fprintf(stderr, "my_access -f file\n"); | 
|  | 29 | + fprintf(stderr, "my_access [-r] [-w] [-x] file\n"); | 
|  | 30 | + fprintf(stderr, "\t-h\tPrint this help message\n"); | 
|  | 31 | + fprintf(stderr, "\t-f\tTest for existence of file\n"); | 
|  | 32 | + fprintf(stderr, "\t-r\tTest whether effective user can read file\n"); | 
|  | 33 | + fprintf(stderr, "\t-w\tTest whether effective user can write file\n"); | 
|  | 34 | + fprintf(stderr, "\t-x\tTest whether effective user can execute file\n"); | 
|  | 35 | + exit(rc); | 
|  | 36 | +} | 
|  | 37 | + | 
|  | 38 | +int my_access(const char *pathname, int mode) | 
|  | 39 | +{ | 
|  | 40 | +} | 
|  | 41 | + | 
|  | 42 | +int | 
|  | 43 | +main(int argc, char *argv[]) | 
|  | 44 | +{ | 
|  | 45 | + int fname; /* Location of filename argument in argv[] */ | 
|  | 46 | + int opt; | 
|  | 47 | + int f_mode = 0; /* F_OK maps to zero (0) */ | 
|  | 48 | + int rwx_mode = 0; | 
|  | 49 | + char *invalid_opt_msg_fmt = "'%c' is an invalid option"; | 
|  | 50 | + char *invalid_opt_msg; | 
|  | 51 | + char *file_missing_msg = "file name is missing"; | 
|  | 52 | + char *conflict_args_msg = "specify either -f or a combination of -r -w -x"; | 
|  | 53 | + | 
|  | 54 | + invalid_opt_msg = malloc(strlen(invalid_opt_msg_fmt)); | 
|  | 55 | + while ((opt = getopt(argc, argv, ":hfrwx")) != -1) | 
|  | 56 | + { | 
|  | 57 | + switch (opt) | 
|  | 58 | + { | 
|  | 59 | + case 'f': f_mode = 1; break; | 
|  | 60 | + case 'h': print_help(NULL, EXIT_SUCCESS); break; | 
|  | 61 | + case 'r': rwx_mode |= R_OK; break; | 
|  | 62 | + case 'w': rwx_mode |= W_OK; break; | 
|  | 63 | + case 'x': rwx_mode |= X_OK; break; | 
|  | 64 | + case '?': | 
|  | 65 | + sprintf(invalid_opt_msg, invalid_opt_msg_fmt, (char)optopt); | 
|  | 66 | + print_help(invalid_opt_msg, EXIT_FAILURE); | 
|  | 67 | + break; | 
|  | 68 | + } | 
|  | 69 | + } | 
|  | 70 | + | 
|  | 71 | + fname = optind; | 
|  | 72 | + | 
|  | 73 | + if (fname >= argc) print_help(file_missing_msg, EXIT_FAILURE); | 
|  | 74 | + if (f_mode == 0) | 
|  | 75 | + { | 
|  | 76 | + if (rwx_mode == 0) print_help(conflict_args_msg, EXIT_FAILURE); | 
|  | 77 | + } | 
|  | 78 | + else | 
|  | 79 | + { | 
|  | 80 | + if (rwx_mode != 0) print_help(conflict_args_msg, EXIT_FAILURE); | 
|  | 81 | + } | 
|  | 82 | + | 
|  | 83 | + exit(EXIT_SUCCESS); | 
|  | 84 | +} | 
0 commit comments