]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-dirent-util.c
Merge pull request #31648 from neighbourhoodie/review-content
[thirdparty/systemd.git] / src / test / test-dirent-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <dirent.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include <sys/stat.h>
7
8 #include "alloc-util.h"
9 #include "dirent-util.h"
10 #include "fs-util.h"
11 #include "mkdir.h"
12 #include "path-util.h"
13 #include "rm-rf.h"
14 #include "stat-util.h"
15 #include "string-util.h"
16 #include "tmpfile-util.h"
17 #include "tests.h"
18
19 TEST (test_dirent_ensure_type) {
20 int r, dir_fd;
21 static struct dirent de = {
22 .d_type = DT_UNKNOWN,
23 .d_name = "test",
24 };
25
26 dir_fd = 0;
27 assert_se(dirent_ensure_type(dir_fd, &de) == -ENOTDIR);
28
29 /* Test when d_name is "." or ".." */
30 strcpy(de.d_name, ".");
31 r = dirent_ensure_type(dir_fd, &de);
32 assert_se(r == 0);
33 assert_se(de.d_type == DT_DIR);
34
35 strcpy(de.d_name, "..");
36 r = dirent_ensure_type(dir_fd, &de);
37 assert_se(r == 0);
38 assert_se(de.d_type == DT_DIR);
39 }
40
41 TEST (test_dirent_is_file) {
42 _cleanup_(rm_rf_physical_and_freep) char *t = NULL;
43 const char *name, *dotfile, *name_alias, *bakfile, *tilda;
44 const struct dirent *de_reg, *de_lnk, *de_dot, *de_bak, *de_tilda;
45 DIR *dir;
46
47 static const struct dirent de_unknown = {
48 .d_type = DT_UNKNOWN,
49 .d_name = "test_unknown",
50 };
51
52 assert_se(mkdtemp_malloc(NULL, &t) >= 0);
53
54 name = strjoina(t, "/test.txt");
55 dotfile = strjoina(t, "/.hidden_file");
56 bakfile = strjoina(t, "/test.bak");
57 tilda = strjoina(t, "/test~");
58 name_alias = strjoina(t, "/test_link");
59
60 assert_se(touch(name) >= 0);
61 assert_se(touch(dotfile) >= 0);
62 assert_se(touch(bakfile) >= 0);
63 assert_se(touch(tilda) >= 0);
64
65 if (symlink(name, name_alias) < 0) {
66 assert_se(IN_SET(errno, EINVAL, ENOSYS, ENOTTY, EPERM));
67 log_tests_skipped_errno(errno, "symlink() not possible");
68 }
69
70 dir = opendir(t);
71 if (!dir) {
72 log_error_errno(errno, "Failed to open directory '%s': %m", t);
73 exit(EXIT_FAILURE);
74 }
75
76 rewinddir(dir);
77 while ((de_reg = readdir_ensure_type(dir)) != NULL)
78 if (strcmp(de_reg->d_name, "test.txt") == 0)
79 break;
80
81 rewinddir(dir);
82 while ((de_lnk = readdir_ensure_type(dir)) != NULL)
83 if (strcmp(de_lnk->d_name, "test_link") == 0)
84 break;
85
86 rewinddir(dir);
87 while ((de_dot = readdir_ensure_type(dir)) != NULL)
88 if (strcmp(de_dot->d_name, ".hidden_file") == 0)
89 break;
90
91 rewinddir(dir);
92 while ((de_bak = readdir(dir)) != NULL)
93 if (strcmp(de_bak->d_name, "test.bak") == 0)
94 break;
95
96 rewinddir(dir);
97 while ((de_tilda = readdir(dir)) != NULL)
98 if (strcmp(de_tilda->d_name, "test~") == 0)
99 break;
100
101 /* Test when d_type is DT_REG, DT_LNK, or DT_UNKNOWN */
102 assert_se(dirent_is_file(de_reg) == true);
103 if (de_lnk)
104 assert_se(dirent_is_file(de_lnk) == true);
105 else
106 log_tests_skipped("de_lnk is NULL, skipping test");
107 assert_se(dirent_is_file(&de_unknown) == true);
108
109 /* Test for hidden files */
110 assert_se(dirent_is_file(de_dot) == false);
111 assert_se(dirent_is_file(de_bak) == false);
112 assert_se(dirent_is_file(de_tilda) == false);
113
114 closedir(dir);
115 }
116
117 TEST (test_dirent_is_file_with_suffix) {
118 _cleanup_(rm_rf_physical_and_freep) char *t = NULL;
119 const char *name, *dotfile, *name_alias, *dotdot, *chr;
120 const struct dirent *de_reg, *de_lnk, *de_dot, *de_dotdot, *de_chr;
121 DIR *dir;
122
123 static const struct dirent de_unknown = {
124 .d_type = DT_UNKNOWN,
125 .d_name = "test_unknown",
126 };
127
128 assert_se(mkdtemp_malloc(NULL, &t) >= 0);
129
130 name = strjoina(t, "/test.txt");
131 dotfile = strjoina(t, "/.hidden_file");
132 dotdot = strjoina(t, "/..dotdot");
133 chr = strjoina(t, "/test_chr");
134 name_alias = strjoina(t, "/test_link");
135
136 assert_se(touch(name) >= 0);
137 assert_se(touch(dotfile) >= 0);
138 assert_se(touch(dotdot) >= 0);
139 assert_se(mknod(chr, 0775 | S_IFCHR, makedev(0, 0)) >= 0);
140
141 if (symlink(name, name_alias) < 0) {
142 assert_se(IN_SET(errno, EINVAL, ENOSYS, ENOTTY, EPERM));
143 log_tests_skipped_errno(errno, "symlink() not possible");
144 }
145
146 dir = opendir(t);
147 if (!dir) {
148 log_error_errno(errno, "Failed to open directory '%s': %m", t);
149 exit(EXIT_FAILURE);
150 }
151
152 rewinddir(dir);
153 while ((de_reg = readdir_ensure_type(dir)) != NULL)
154 if (strcmp(de_reg->d_name, "test.txt") == 0)
155 break;
156
157 rewinddir(dir);
158 while ((de_lnk = readdir_ensure_type(dir)) != NULL)
159 if (strcmp(de_lnk->d_name, "test_link") == 0)
160 break;
161
162 rewinddir(dir);
163 while ((de_dot = readdir_ensure_type(dir)) != NULL)
164 if (strcmp(de_dot->d_name, ".hidden_file") == 0)
165 break;
166
167 rewinddir(dir);
168 while ((de_dotdot = readdir(dir)) != NULL)
169 if (strcmp(de_dotdot->d_name, "..dotdot") == 0)
170 break;
171
172 rewinddir(dir);
173 while ((de_chr = readdir(dir)) != NULL)
174 if (strcmp(de_chr->d_name, "test_chr") == 0)
175 break;
176
177 /* Test when d_type is not DT_REG, DT_LNK, or DT_UNKNOWN */
178 assert_se(!dirent_is_file_with_suffix(de_chr, NULL));
179
180 /* Test when suffix is NULL */
181 assert_se(dirent_is_file_with_suffix(de_reg, NULL) == true);
182 if (de_lnk)
183 assert_se(dirent_is_file_with_suffix(de_lnk, NULL) == true);
184 else
185 log_tests_skipped("de_lnk is NULL, skipping test");
186 assert_se(dirent_is_file_with_suffix(&de_unknown, NULL) == true);
187
188 /* Test for present suffix */
189 assert_se(dirent_is_file_with_suffix(de_reg, "txt") == true);
190 if (de_lnk)
191 assert_se(dirent_is_file_with_suffix(de_lnk, "link") == true);
192 else
193 log_tests_skipped("de_lnk is NULL, skipping test");
194 assert_se(dirent_is_file_with_suffix(&de_unknown, "unknown") == true);
195
196 /* Test for absent suffix */
197 assert_se(dirent_is_file_with_suffix(de_reg, "svg") == false);
198 if (de_lnk)
199 assert_se(dirent_is_file_with_suffix(de_lnk, "pdf") == false);
200 else
201 log_tests_skipped("de_lnk is NULL, skipping test");
202 assert_se(dirent_is_file_with_suffix(&de_unknown, "yes") == false);
203
204 /* Test for dot and dot-dot */
205 assert_se(dirent_is_file_with_suffix(de_dot, NULL) == false);
206 assert_se(dirent_is_file_with_suffix(de_dotdot, NULL) == false);
207
208 closedir(dir);
209 }
210
211 DEFINE_TEST_MAIN(LOG_INFO);