FreeRDP
Loading...
Searching...
No Matches
TestPathRemoveDirectoryRecursive.c
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <sys/stat.h>
6
7#include <winpr/crt.h>
8#include <winpr/path.h>
9#include <winpr/file.h>
10
11static BOOL make_file(const char* base, const char* name)
12{
13 char path[512] = WINPR_C_ARRAY_INIT;
14 (void)_snprintf(path, sizeof(path), "%s/%s", base, name);
15 FILE* file = fopen(path, "wb");
16 if (!file)
17 return FALSE;
18 const BOOL ok = fputs("data", file) >= 0;
19 return (fclose(file) == 0) && ok;
20}
21
22static BOOL make_dir(const char* base, const char* name)
23{
24 char path[512] = WINPR_C_ARRAY_INIT;
25 (void)_snprintf(path, sizeof(path), "%s/%s", base, name);
26 return mkdir(path, 0700) == 0;
27}
28
29static BOOL make_link(const char* base, const char* target, const char* name)
30{
31 char path[512] = WINPR_C_ARRAY_INIT;
32 (void)_snprintf(path, sizeof(path), "%s/%s", base, name);
33 return symlink(target, path) == 0;
34}
35
36static BOOL exists(const char* base, const char* name)
37{
38 struct stat st = WINPR_C_ARRAY_INIT;
39 char path[512] = WINPR_C_ARRAY_INIT;
40 (void)_snprintf(path, sizeof(path), "%s/%s", base, name);
41 return lstat(path, &st) == 0;
42}
43
44static BOOL remove_below(const char* base, const char* name)
45{
46 char path[512] = WINPR_C_ARRAY_INIT;
47 (void)_snprintf(path, sizeof(path), "%s/%s", base, name);
48 return winpr_RemoveDirectory_RecursiveA(path);
49}
50
51/* The tree goes, with its directories and everything in them */
52static BOOL test_tree(const char* base)
53{
54 if (!make_dir(base, "tree") || !make_dir(base, "tree/sub") || !make_dir(base, "tree/empty") ||
55 !make_file(base, "tree/a") || !make_file(base, "tree/sub/b"))
56 return FALSE;
57 return remove_below(base, "tree") && !exists(base, "tree");
58}
59
60/* A link goes, and what it points to stays */
61static BOOL test_links_stay_out(const char* base)
62{
63 if (!make_dir(base, "kept") || !make_file(base, "kept/keep") || !make_file(base, "keep2") ||
64 !make_dir(base, "links") || !make_dir(base, "links/sub") ||
65 !make_link(base, "../kept", "links/to-dir") ||
66 !make_link(base, "../../kept", "links/sub/deep") ||
67 !make_link(base, "../keep2", "links/to-file"))
68 return FALSE;
69
70 return remove_below(base, "links") && !exists(base, "links") && exists(base, "kept/keep") &&
71 exists(base, "keep2");
72}
73
74/* The named path itself may be the link */
75static BOOL test_named_link(const char* base)
76{
77 if (!make_link(base, "kept", "link"))
78 return FALSE;
79 return remove_below(base, "link") && !exists(base, "link") && exists(base, "kept/keep");
80}
81
82int TestPathRemoveDirectoryRecursive(int argc, char* argv[])
83{
84 WINPR_UNUSED(argc);
85 WINPR_UNUSED(argv);
86
87 int rc = -1;
88 char base[] = "/tmp/TestPathRemoveDirectoryRecursive.XXXXXX";
89 if (!mkdtemp(base))
90 return -1;
91
92 if (!test_tree(base))
93 (void)fprintf(stderr, "a tree was not removed\n");
94 else if (!test_links_stay_out(base))
95 (void)fprintf(stderr, "a link inside was followed\n");
96 else if (!test_named_link(base))
97 (void)fprintf(stderr, "the named link was followed\n");
98 else
99 rc = 0;
100
101 (void)winpr_RemoveDirectory_RecursiveA(base);
102 return rc;
103}