XBPS Library API 20250615
The X Binary Package System
util_path/main.c
1/*-
2 * Copyright (c) 2012-2014 Juan Romero Pardines.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *-
25 */
26#include <string.h>
27#include <limits.h>
28
29#include <atf-c.h>
30#include <xbps.h>
31
32ATF_TC(xbps_path_clean);
33
34ATF_TC_HEAD(xbps_path_clean, tc)
35{
36 atf_tc_set_md_var(tc, "descr", "Test xbps_path_clean");
37}
38
39ATF_TC_BODY(xbps_path_clean, tc)
40{
41 char buf[PATH_MAX];
42 ssize_t len;
43#define CLEAN(a, b) \
44 xbps_strlcpy(buf, a, sizeof (buf)); \
45 len = xbps_path_clean(buf); \
46 ATF_CHECK_EQ(len, sizeof (b)-1); \
47 ATF_CHECK_STREQ(buf, b)
48
49 /* Already clean */
50 CLEAN("abc", "abc");
51 CLEAN("abc/def", "abc/def");
52 CLEAN("a/b/c", "a/b/c");
53 CLEAN(".", ".");
54 CLEAN("..", "..");
55 CLEAN("../..", "../..");
56 CLEAN("../../abc", "../../abc");
57 CLEAN("/abc", "/abc");
58 CLEAN("/", "/");
59
60 /* Empty is current dir */
61 CLEAN("", ".");
62
63 /* Remove trailing slash */
64 CLEAN("abc/", "abc");
65 CLEAN("abc/def/", "abc/def");
66 CLEAN("a/b/c/", "a/b/c");
67 CLEAN("./", ".");
68 CLEAN("../", "..");
69 CLEAN("../../", "../..");
70 CLEAN("/abc/", "/abc");
71
72 /* Remove doubled slash */
73 CLEAN("abc//def//ghi", "abc/def/ghi");
74 CLEAN("//abc", "/abc");
75 CLEAN("///abc", "/abc");
76 CLEAN("//abc//", "/abc");
77 CLEAN("abc//", "abc");
78
79 /* Remove . elements */
80 CLEAN("abc/./def", "abc/def");
81 CLEAN("/./abc/def", "/abc/def");
82 CLEAN("abc/.", "abc");
83
84 /* Remove .. elements */
85 CLEAN("abc/def/ghi/../jkl", "abc/def/jkl");
86 CLEAN("abc/def/../ghi/../jkl", "abc/jkl");
87 CLEAN("abc/def/..", "abc");
88 CLEAN("abc/def/../..", ".");
89 CLEAN("/abc/def/../..", "/");
90 CLEAN("abc/def/../../..", "..");
91 CLEAN("/abc/def/../../..", "/");
92 CLEAN("abc/def/../../../ghi/jkl/../../../mno", "../../mno");
93 CLEAN("/../abc", "/abc");
94
95 /* Combinations */
96 CLEAN("abc/./../def", "def");
97 CLEAN("abc//./../def", "def");
98 CLEAN("abc/../../././../def", "../../def");
99
100 /* Add test case with "hidden" dir */
101 CLEAN("foo//bar/.fizz/buzz", "foo/bar/.fizz/buzz");
102 CLEAN(".fizz/buzz", ".fizz/buzz");
103 CLEAN(".fizz", ".fizz");
104}
105
106ATF_TC(xbps_path_rel);
107
108ATF_TC_HEAD(xbps_path_rel, tc)
109{
110 atf_tc_set_md_var(tc, "descr", "Test xbps_path_rel");
111}
112
113ATF_TC_BODY(xbps_path_rel, tc)
114{
115 char buf[PATH_MAX];
116 ssize_t len;
117
118#define REL(a, b, c) \
119 len = xbps_path_rel(buf, sizeof buf, a, b); \
120 ATF_CHECK_EQ(len, sizeof (c)-1); \
121 ATF_CHECK_STREQ(buf, c)
122
123 REL("/root/usr/bin/tar", "/root/usr/bin/gtar", "gtar");
124
125 REL("/root/usr/bin/java", "/root/usr/lib/jvm/jdk1.8.0_202/bin/java",
126 "../lib/jvm/jdk1.8.0_202/bin/java");
127
128 REL("/root/usr/..", "/root/usr/lib/..", "root/usr");
129 REL("/root/usr/../bin", "/root/usr/lib/..", "usr");
130 REL("/root/usr/../bin", "/root/usr/", "usr");
131
132 REL("/root/usr/bin/tar", "/root/usr/libexec/gtar", "../libexec/gtar");
133 REL("/root/usr/bin//tar", "/root/usr/libexec/gtar", "../libexec/gtar");
134 REL("/root/usr/bin//tar", "/root/usr/libexec//gtar", "../libexec/gtar");
135 REL("/usr/bin/file", "/usr/bin/fileA", "fileA");
136}
137
138ATF_TC(xbps_path_join);
139
140ATF_TC_HEAD(xbps_path_join, tc)
141{
142 atf_tc_set_md_var(tc, "descr", "Test xbps_path_join");
143}
144
145ATF_TC_BODY(xbps_path_join, tc)
146{
147 char buf[6];
148 ssize_t len;
149
150 len = xbps_path_join(buf, sizeof buf, "a", "b", "c", (char *)NULL);
151 ATF_CHECK_EQ(len, 5);
152 ATF_CHECK_STREQ(buf, "a/b/c");
153
154 len = xbps_path_join(buf, sizeof buf, "a/", "/b/", "/c", (char *)NULL);
155 ATF_CHECK_EQ(len, 5);
156 ATF_CHECK_STREQ(buf, "a/b/c");
157
158 len = xbps_path_join(buf, sizeof buf, "abc", "def", (char *)NULL);
159 ATF_CHECK_EQ(len, -1);
160
161 len = xbps_path_join(buf, sizeof buf, "abcd", "ef", (char *)NULL);
162 ATF_CHECK_EQ(len, -1);
163
164 len = xbps_path_join(buf, sizeof buf, "ab", "c", (char *)NULL);
165 ATF_CHECK_EQ(len, 4);
166 ATF_CHECK_STREQ(buf, "ab/c");
167
168 len = xbps_path_join(buf, sizeof buf, "ab/", "/c", (char *)NULL);
169 ATF_CHECK_EQ(len, 4);
170 ATF_CHECK_STREQ(buf, "ab/c");
171
172 len = xbps_path_join(buf, sizeof buf, "/ab/", "/c", (char *)NULL);
173 ATF_CHECK_EQ(len, sizeof ("/ab/c") - 1);
174 ATF_CHECK_STREQ(buf, "/ab/c");
175
176 len = xbps_path_join(buf, sizeof buf, "/a/", "/b/", (char *)NULL);
177 ATF_CHECK_EQ(len, sizeof ("/a/b/") - 1);
178 ATF_CHECK_STREQ(buf, "/a/b/");
179
180 len = xbps_path_join(buf, sizeof buf, "", "/a/", (char *)NULL);
181 ATF_CHECK_EQ(len, sizeof ("/a/") - 1);
182 ATF_CHECK_STREQ(buf, "/a/");
183
184 len = xbps_path_join(buf, sizeof buf, "a", "b/", (char *)NULL);
185 ATF_CHECK_EQ(len, sizeof ("a/b/") - 1);
186 ATF_CHECK_STREQ(buf, "a/b/");
187
188 len = xbps_path_join(buf, sizeof buf, "/", "a/", (char *)NULL);
189 ATF_CHECK_EQ(len, sizeof ("/a/") - 1);
190 ATF_CHECK_STREQ(buf, "/a/");
191
192 len = xbps_path_join(buf, sizeof buf, "/", "a", (char *)NULL);
193 ATF_CHECK_EQ(len, sizeof ("/a") - 1);
194 ATF_CHECK_STREQ(buf, "/a");
195}
196
197ATF_TC(xbps_path_append);
198
199ATF_TC_HEAD(xbps_path_append, tc)
200{
201 atf_tc_set_md_var(tc, "descr", "Test xbps_path_append");
202}
203
204ATF_TC_BODY(xbps_path_append, tc)
205{
206 char buf[16];
207 ssize_t len;
208
209 /* empty prefix */
210 xbps_strlcpy(buf, "fizz", sizeof buf);
211 len = xbps_path_append(buf, sizeof buf, "");
212 ATF_CHECK_EQ(len, sizeof ("fizz") - 1);
213 ATF_CHECK_STREQ(buf, "fizz");
214
215 /* empty dst */
216 buf[0] = '\0';
217 len = xbps_path_append(buf, sizeof buf, "buzz");
218 ATF_CHECK_EQ(len, sizeof ("buzz") - 1);
219 ATF_CHECK_STREQ(buf, "buzz");
220
221 /* add slash */
222 xbps_strlcpy(buf, "fizz", sizeof buf);
223 len = xbps_path_append(buf, sizeof buf, "buzz");
224 ATF_CHECK_EQ(len, sizeof ("fizz/buzz") - 1);
225 ATF_CHECK_STREQ(buf, "fizz/buzz");
226
227 /* already has slash in dst */
228 xbps_strlcpy(buf, "fizz/", sizeof buf);
229 len = xbps_path_append(buf, sizeof buf, "buzz");
230 ATF_CHECK_EQ(len, sizeof ("fizz/buzz") - 1);
231 ATF_CHECK_STREQ(buf, "fizz/buzz");
232
233 /* already has slash in suffix */
234 xbps_strlcpy(buf, "fizz", sizeof buf);
235 len = xbps_path_append(buf, sizeof buf, "/buzz");
236 ATF_CHECK_EQ(len, sizeof ("fizz/buzz") - 1);
237 ATF_CHECK_STREQ(buf, "fizz/buzz");
238
239 /* slash in dst and suffix */
240 xbps_strlcpy(buf, "fizz/", sizeof buf);
241 len = xbps_path_append(buf, sizeof buf, "/buzz");
242 ATF_CHECK_EQ(len, sizeof ("fizz/buzz") - 1);
243 ATF_CHECK_STREQ(buf, "fizz/buzz");
244
245 xbps_strlcpy(buf, "abcdefghijklmno", sizeof buf);
246 len = xbps_path_append(buf, sizeof buf, "pqrstuvwxyz");
247 ATF_CHECK_EQ(len, -1);
248
249 xbps_strlcpy(buf, "abcdefghijklmn", sizeof buf);
250 len = xbps_path_append(buf, sizeof buf, "opqrstuvwxyz");
251 ATF_CHECK_EQ(len, -1);
252
253 xbps_strlcpy(buf, "abcdefghijklm", sizeof buf);
254 len = xbps_path_append(buf, sizeof buf, "nopqrstuvwxyz");
255 ATF_CHECK_EQ(len, -1);
256
257 xbps_strlcpy(buf, "abcdefghijklmno/", sizeof buf);
258 len = xbps_path_append(buf, sizeof buf, "pqrstuvwxyz");
259 ATF_CHECK_EQ(len, -1);
260
261 xbps_strlcpy(buf, "abcdefghijklmn/", sizeof buf);
262 len = xbps_path_append(buf, sizeof buf, "opqrstuvwxyz");
263 ATF_CHECK_EQ(len, -1);
264
265 xbps_strlcpy(buf, "abcdefghijklm/", sizeof buf);
266 len = xbps_path_append(buf, sizeof buf, "nopqrstuvwxyz");
267 ATF_CHECK_EQ(len, -1);
268
269 xbps_strlcpy(buf, "abcdefghijklmno", sizeof buf);
270 len = xbps_path_append(buf, sizeof buf, "");
271 ATF_CHECK_EQ(len, sizeof ("abcdefghijklmno") - 1);
272 ATF_CHECK_STREQ(buf, "abcdefghijklmno");
273
274 xbps_strlcpy(buf, "abcdefghijklmn/", sizeof buf);
275 len = xbps_path_append(buf, sizeof buf, "");
276 ATF_CHECK_EQ(len, sizeof ("abcdefghijklmn/") - 1);
277 ATF_CHECK_STREQ(buf, "abcdefghijklmn/");
278
279 xbps_strlcpy(buf, "", sizeof buf);
280 len = xbps_path_append(buf, sizeof buf, "abcdefghijklmno");
281 ATF_CHECK_EQ(len, sizeof ("abcdefghijklmno") - 1);
282 ATF_CHECK_STREQ(buf, "abcdefghijklmno");
283
284 xbps_strlcpy(buf, "", sizeof buf);
285 len = xbps_path_append(buf, sizeof buf, "abcdefghijklmn/");
286 ATF_CHECK_EQ(len, sizeof ("abcdefghijklmn/") - 1);
287 ATF_CHECK_STREQ(buf, "abcdefghijklmn/");
288}
289
290ATF_TC(xbps_path_prepend);
291
292ATF_TC_HEAD(xbps_path_prepend, tc)
293{
294 atf_tc_set_md_var(tc, "descr", "Test xbps_path_prepend");
295}
296
297ATF_TC_BODY(xbps_path_prepend, tc)
298{
299 char buf[16];
300 ssize_t len;
301
302 /* empty prefix */
303 xbps_strlcpy(buf, "buzz", sizeof buf);
304 len = xbps_path_prepend(buf, sizeof buf, "");
305 ATF_CHECK_EQ(len, sizeof ("buzz") - 1);
306 ATF_CHECK_STREQ(buf, "buzz");
307
308 /* empty dst */
309 buf[0] = '\0';
310 len = xbps_path_prepend(buf, sizeof buf, "buzz");
311 ATF_CHECK_EQ(len, sizeof ("buzz") - 1);
312 ATF_CHECK_STREQ(buf, "buzz");
313
314 /* add slash */
315 xbps_strlcpy(buf, "buzz", sizeof buf);
316 len = xbps_path_prepend(buf, sizeof buf, "fizz");
317 ATF_CHECK_EQ(len, sizeof ("fizz/buzz") - 1);
318 ATF_CHECK_STREQ(buf, "fizz/buzz");
319
320 /* already has slash in dst */
321 xbps_strlcpy(buf, "/buzz", sizeof buf);
322 len = xbps_path_prepend(buf, sizeof buf, "fizz");
323 ATF_CHECK_EQ(len, sizeof ("fizz/buzz") - 1);
324 ATF_CHECK_STREQ(buf, "fizz/buzz");
325
326 /* already has slash in prefix */
327 xbps_strlcpy(buf, "buzz", sizeof buf);
328 len = xbps_path_prepend(buf, sizeof buf, "fizz/");
329 ATF_CHECK_EQ(len, sizeof ("fizz/buzz") - 1);
330 ATF_CHECK_STREQ(buf, "fizz/buzz");
331
332 /* slash in dst and prefix */
333 xbps_strlcpy(buf, "/buzz", sizeof buf);
334 len = xbps_path_prepend(buf, sizeof buf, "fizz/");
335 ATF_CHECK_EQ(len, sizeof ("fizz/buzz") - 1);
336 ATF_CHECK_STREQ(buf, "fizz/buzz");
337
338 /* check truncation no slashes */
339 xbps_strlcpy(buf, "bar/buzz", sizeof buf);
340 len = xbps_path_prepend(buf, sizeof buf, "fizz/foo");
341 ATF_CHECK_EQ(len, -1);
342
343 /* check truncation slash in dst*/
344 xbps_strlcpy(buf, "/bar/buzz", sizeof buf);
345 len = xbps_path_prepend(buf, sizeof buf, "fizz/foo");
346 ATF_CHECK_EQ(len, -1);
347
348 /* check truncation slash in prefix */
349 xbps_strlcpy(buf, "bar/buzz", sizeof buf);
350 len = xbps_path_prepend(buf, sizeof buf, "fizz/foo/");
351 ATF_CHECK_EQ(len, -1);
352
353 /* check truncation slash in both */
354 xbps_strlcpy(buf, "/bar/buzz", sizeof buf);
355 len = xbps_path_prepend(buf, sizeof buf, "fizz/foo/");
356 ATF_CHECK_EQ(len, -1);
357
358 /* check truncation */
359 xbps_strlcpy(buf, "pqrstuvwxyz", sizeof buf);
360 len = xbps_path_prepend(buf, sizeof buf, "abcdefghijklmno");
361 ATF_CHECK_EQ(len, -1);
362
363 xbps_strlcpy(buf, "/opqrstuvwxyz", sizeof buf);
364 len = xbps_path_prepend(buf, sizeof buf, "abcdefghijklmn/");
365 ATF_CHECK_EQ(len, -1);
366
367 xbps_strlcpy(buf, "/nopqrstuvwxyz", sizeof buf);
368 len = xbps_path_prepend(buf, sizeof buf, "abcdefghijklm/");
369 ATF_CHECK_EQ(len, -1);
370
371 xbps_strlcpy(buf, "opqrstuvwxyz", sizeof buf);
372 len = xbps_path_prepend(buf, sizeof buf, "abcdefghijklmn");
373 ATF_CHECK_EQ(len, -1);
374
375 xbps_strlcpy(buf, "nopqrstuvwxyz", sizeof buf);
376 len = xbps_path_prepend(buf, sizeof buf, "abcdefghijklm");
377 ATF_CHECK_EQ(len, -1);
378
379 xbps_strlcpy(buf, "", sizeof buf);
380 len = xbps_path_prepend(buf, sizeof buf, "abcdefghijklmno");
381 ATF_CHECK_EQ(len, sizeof ("abcdefghijklmno") - 1);
382 ATF_CHECK_STREQ(buf, "abcdefghijklmno");
383
384 xbps_strlcpy(buf, "", sizeof buf);
385 len = xbps_path_prepend(buf, sizeof buf, "abcdefghijklm/");
386 ATF_CHECK_EQ(len, sizeof ("abcdefghijklm/") - 1);
387 ATF_CHECK_STREQ(buf, "abcdefghijklm/");
388}
389
390ATF_TP_ADD_TCS(tp)
391{
392 ATF_TP_ADD_TC(tp, xbps_path_clean);
393 ATF_TP_ADD_TC(tp, xbps_path_rel);
394 ATF_TP_ADD_TC(tp, xbps_path_join);
395 ATF_TP_ADD_TC(tp, xbps_path_append);
396 ATF_TP_ADD_TC(tp, xbps_path_prepend);
397 return atf_no_error();
398}
ssize_t xbps_path_append(char *dst, size_t len, const char *suffix)
Definition util_path.c:219
size_t xbps_strlcpy(char *dst, const char *src, size_t dstsize)
Definition util.c:575
ssize_t xbps_path_clean(char *path)
Definition util_path.c:67
ssize_t xbps_path_prepend(char *dst, size_t len, const char *prefix)
Definition util_path.c:249
ssize_t xbps_path_join(char *dst, size_t len,...)
Definition util_path.c:208
ssize_t xbps_path_rel(char *dst, size_t len, const char *from, const char *to)
Definition util_path.c:131