Line data Source code
1 : #include "sute.h"
2 : #include <sys/stat.h>
3 : #include <unistd.h>
4 : #include <limits.h>
5 :
6 : /**
7 : * @brief Unit tests for file_check_access().
8 : *
9 : * @details
10 : * - Verifies readable absolute paths are detected immediately.
11 : * - Verifies relative paths are resolved via config->running_dir and marked readable.
12 : * - Verifies missing files return FILE_NOT_FOUND without errors.
13 : * - Verifies unreadable paths return FILE_ACCESS_DENIED.
14 : */
15 1 : Return test0026(void)
16 : {
17 1 : INITTEST;
18 :
19 1 : const char *tmpdir = getenv("TMPDIR");
20 1 : ASSERT(tmpdir != NULL);
21 :
22 : /* Absolute path should be reported readable */
23 : {
24 : char abs_path[PATH_MAX];
25 1 : const int written = snprintf(abs_path,sizeof(abs_path),"%s/%s",tmpdir,"test0026_abs.txt");
26 1 : ASSERT(written > 0 && (size_t)written < sizeof(abs_path));
27 :
28 1 : FILE *f = fopen(abs_path,"w");
29 1 : ASSERT(f != NULL);
30 1 : fclose(f);
31 :
32 1 : const size_t len = strlen(abs_path);
33 1 : FileAccessStatus rc = file_check_access(abs_path,len);
34 1 : ASSERT(rc == FILE_ACCESS_ALLOWED);
35 :
36 1 : remove(abs_path);
37 : }
38 :
39 : /* Relative path should resolve using config->running_dir */
40 : {
41 1 : const char *relative_name = "test0026_rel.txt";
42 : char rel_full_path[PATH_MAX];
43 1 : const int written = snprintf(rel_full_path,sizeof(rel_full_path),"%s/%s",tmpdir,relative_name);
44 1 : ASSERT(written > 0 && (size_t)written < sizeof(rel_full_path));
45 :
46 1 : FILE *f = fopen(rel_full_path,"w");
47 1 : ASSERT(f != NULL);
48 1 : fclose(f);
49 :
50 1 : char *prev_dir = config->running_dir;
51 1 : long int prev_len = config->running_dir_size;
52 :
53 1 : config->running_dir = strdup(tmpdir);
54 1 : ASSERT(config->running_dir != NULL);
55 1 : config->running_dir_size = (long int)strlen(tmpdir) + 1; // includes terminating '\0' like determine_running_dir()
56 :
57 1 : const size_t len = strlen(relative_name);
58 1 : FileAccessStatus rc = file_check_access(relative_name,len);
59 :
60 1 : free(config->running_dir);
61 1 : config->running_dir = prev_dir;
62 1 : config->running_dir_size = prev_len;
63 1 : remove(rel_full_path);
64 :
65 1 : ASSERT(rc == FILE_ACCESS_ALLOWED);
66 : }
67 :
68 : /* Missing file should report not found without errors */
69 : {
70 : char missing_path[PATH_MAX];
71 1 : const int written = snprintf(missing_path,sizeof(missing_path),"%s/%s",tmpdir,"test0026_missing.txt");
72 1 : ASSERT(written > 0 && (size_t)written < sizeof(missing_path));
73 1 : remove(missing_path); // ensure absence
74 :
75 1 : const size_t len = strlen(missing_path);
76 1 : FileAccessStatus rc = file_check_access(missing_path,len);
77 :
78 1 : ASSERT(rc == FILE_NOT_FOUND);
79 : }
80 :
81 : /* Unreadable path (directory without permissions) should report denied */
82 : {
83 : char locked_dir[PATH_MAX];
84 1 : const int dir_written = snprintf(locked_dir,sizeof(locked_dir),"%s/%s",tmpdir,"test0026_locked_dir");
85 1 : ASSERT(dir_written > 0 && (size_t)dir_written < sizeof(locked_dir));
86 :
87 1 : int mk_rc = mkdir(locked_dir,0700);
88 1 : ASSERT(mk_rc == 0);
89 :
90 : char locked_file_path[PATH_MAX];
91 1 : const int file_written = snprintf(locked_file_path,sizeof(locked_file_path),"%s/%s",locked_dir,"file.txt");
92 1 : ASSERT(file_written > 0 && (size_t)file_written < sizeof(locked_file_path));
93 :
94 1 : FILE *f = fopen(locked_file_path,"w");
95 1 : ASSERT(f != NULL);
96 1 : fclose(f);
97 :
98 : /* lock directory */
99 1 : ASSERT(chmod(locked_dir,0000) == 0);
100 :
101 1 : const size_t len = strlen(locked_file_path);
102 1 : FileAccessStatus rc = file_check_access(locked_file_path,len);
103 :
104 : /* restore permissions for cleanup */
105 1 : ASSERT(chmod(locked_dir,0700) == 0);
106 1 : ASSERT(remove(locked_file_path) == 0);
107 1 : ASSERT(rmdir(locked_dir) == 0);
108 :
109 1 : ASSERT(rc == FILE_ACCESS_DENIED);
110 : }
111 :
112 1 : RETURN_STATUS;
113 : }
|