/* * read-access-check.c - check if the user has read permission to a given * file. If not, check where the problem lies. * * Background: In order to read from a file, we must have execute permission * in all directories leading to this file, as well as read access * to the file itself. For example, to read from file * "/etc/config/blabla.conf", we must have X permission on '/etc' * and on '/etc/config', as well as R permission on * "/etc/config/blabla.conf" itself. * * Algorithm: split the file path to its directories, make sure the directory * exists and that the user has execute permission to all * directories. Finally check that the file exists, and that the * user has read permission to the file itself. */ #include /* standard input/output routines. */ #include /* access(), R_OK etc. */ #include /* strchr(), etc. */ #include /* malloc(), etc. */ /* * function: main. * input: full path to a file. * output: 'OK' if permission is granted, or 'ACCESS DENIED' and a * detailed explanation if some problem was found. */ void main(int argc, char* argv[]) { char* file_path; /* full path to file. */ char* dir_path; /* full path to a directory. */ char* p_slash; /* location of next '/' in path. */ /* read command line arguments */ if (argc != 2 || !argv[1]) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(1); } file_path = argv[1]; dir_path = (char*)malloc(strlen(file_path)+1); if (!dir_path) { fprintf(stderr, "out of memory\n"); exit(1); } /* scan all directories in the path and check each of them. */ p_slash = file_path; while ( (p_slash = strchr(p_slash, '/')) != NULL) { /* copy directory path (including trailing slash) into dir_path. */ strncpy(dir_path, file_path, p_slash-file_path+1); dir_path[p_slash-file_path+1] = '\0'; /* check existance and execute permission for this directory. */ if (access(dir_path, F_OK) == -1) { printf("%s: Directory '%s' in the path does not exist.\n", "ACCESS DENIED", dir_path); exit(2); } if (access(dir_path, X_OK) == -1) { printf("%s: Directory '%s' in the path - no 'X' permission.\n", "ACCESS DENIED", dir_path); exit(2); } /* skip the current slash, so the next strchr() call will find */ /* the next slash in the file path. */ p_slash++; } /* all directories in the path exist and are executable. */ /* now check existance and read access to the file itself. */ if (access(file_path, F_OK) == -1) { printf("%s: File does not exist.\n", "ACCESS DENIED"); exit(2); } if (access(file_path, R_OK) == -1) { printf("%s: no read access to file.\n", "ACCESS DENIED"); exit(2); } /* all tests passed. */ printf("OK\n"); }