Serenity Operating System
1/*
2 * Copyright (c) 2021, the SerenityOS developers.
3 * Copyright (c) 2021, Brian Gianforcaro <bgianf@serenityos.org>
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8#include <AK/DeprecatedString.h>
9#include <LibCore/DeprecatedFile.h>
10#include <LibTest/TestCase.h>
11#include <fcntl.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/mman.h>
16#include <sys/wait.h>
17#include <unistd.h>
18
19TEST_CASE(test_mktemp_unique_filename)
20{
21 u8* ptr = (u8*)mmap(nullptr, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
22 EXPECT(ptr != MAP_FAILED);
23
24 if (fork() == 0) {
25 char path[] = "/tmp/test.mktemp.XXXXXX";
26 auto temp_path = DeprecatedString::formatted("{}", mktemp(path));
27 EXPECT(temp_path.characters());
28 unlink(path);
29
30 memcpy(&ptr[0], temp_path.characters(), temp_path.length());
31
32 exit(EXIT_SUCCESS);
33 } else {
34 wait(NULL);
35
36 auto path1 = DeprecatedString::formatted("{}", reinterpret_cast<char const*>(ptr));
37
38 char path[] = "/tmp/test.mktemp.XXXXXX";
39 auto path2 = DeprecatedString::formatted("{}", mktemp(path));
40 EXPECT(path2.characters());
41 unlink(path);
42
43 EXPECT_NE(path1, path2);
44 }
45
46 munmap(ptr, sizeof(*ptr));
47}
48
49TEST_CASE(test_mkdtemp_unique_filename)
50{
51 u8* ptr = (u8*)mmap(nullptr, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
52 EXPECT_NE(ptr, MAP_FAILED);
53
54 if (fork() == 0) {
55 char path[] = "/tmp/test.mkdtemp.XXXXXX";
56 auto temp_path = DeprecatedString::formatted("{}", mkdtemp(path));
57 EXPECT(temp_path.characters());
58 rmdir(path);
59
60 memcpy(&ptr[0], temp_path.characters(), temp_path.length());
61
62 exit(EXIT_SUCCESS);
63 } else {
64 wait(NULL);
65
66 auto path1 = DeprecatedString::formatted("{}", reinterpret_cast<char const*>(ptr));
67
68 char path[] = "/tmp/test.mkdtemp.XXXXXX";
69 auto path2 = DeprecatedString::formatted("{}", mkdtemp(path));
70 EXPECT(path2.characters());
71 rmdir(path);
72
73 EXPECT_NE(path1, path2);
74 }
75
76 munmap(ptr, sizeof(*ptr));
77}
78
79TEST_CASE(test_mkstemp_unique_filename)
80{
81 u8* ptr = (u8*)mmap(nullptr, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
82 EXPECT_NE(ptr, MAP_FAILED);
83
84 if (fork() == 0) {
85 char path[] = "/tmp/test.mkstemp.XXXXXX";
86 auto fd = mkstemp(path);
87 EXPECT_NE(fd, -1);
88
89 auto temp_path_or_error = Core::DeprecatedFile::read_link(DeprecatedString::formatted("/proc/{}/fd/{}", getpid(), fd));
90 EXPECT(!temp_path_or_error.is_error());
91
92 auto temp_path = temp_path_or_error.release_value();
93 EXPECT(temp_path.characters());
94
95 close(fd);
96 unlink(path);
97
98 memcpy(&ptr[0], temp_path.characters(), temp_path.length());
99
100 exit(EXIT_SUCCESS);
101 } else {
102 wait(NULL);
103
104 auto path1 = DeprecatedString::formatted("{}", reinterpret_cast<char const*>(ptr));
105
106 char path[] = "/tmp/test.mkstemp.XXXXXX";
107 auto fd = mkstemp(path);
108 EXPECT(fd != -1);
109
110 auto path2_or_error = Core::DeprecatedFile::read_link(DeprecatedString::formatted("/proc/{}/fd/{}", getpid(), fd));
111 EXPECT(!path2_or_error.is_error());
112
113 auto path2 = path2_or_error.release_value();
114 EXPECT(path2.characters());
115
116 close(fd);
117 unlink(path);
118
119 EXPECT_NE(path1, path2);
120 }
121
122 munmap(ptr, sizeof(*ptr));
123}
124
125TEST_CASE(test_mkstemps_unique_filename)
126{
127 u8* ptr = (u8*)mmap(nullptr, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
128 EXPECT_NE(ptr, MAP_FAILED);
129
130 if (fork() == 0) {
131 char path[] = "/tmp/test.mkstemps.prefixXXXXXXsuffix";
132 auto fd = mkstemps(path, 6);
133 EXPECT_NE(fd, -1);
134
135 auto temp_path_or_error = Core::DeprecatedFile::read_link(DeprecatedString::formatted("/proc/{}/fd/{}", getpid(), fd));
136 EXPECT(!temp_path_or_error.is_error());
137
138 auto temp_path = temp_path_or_error.release_value();
139 EXPECT(temp_path.characters());
140
141 close(fd);
142 unlink(path);
143
144 EXPECT(temp_path.starts_with("/tmp/test.mkstemps.prefix"sv));
145 EXPECT(temp_path.ends_with("suffix"sv));
146 EXPECT_EQ(strlen(path), temp_path.length());
147
148 memcpy(&ptr[0], temp_path.characters(), temp_path.length());
149
150 exit(EXIT_SUCCESS);
151 } else {
152 wait(NULL);
153
154 auto path1 = DeprecatedString::formatted("{}", reinterpret_cast<char const*>(ptr));
155
156 char path[] = "/tmp/test.mkstemps.prefixXXXXXXsuffix";
157 auto fd = mkstemps(path, 6);
158 EXPECT(fd != -1);
159
160 auto path2_or_error = Core::DeprecatedFile::read_link(DeprecatedString::formatted("/proc/{}/fd/{}", getpid(), fd));
161 EXPECT(!path2_or_error.is_error());
162
163 auto path2 = path2_or_error.release_value();
164 EXPECT(path2.characters());
165
166 close(fd);
167 unlink(path);
168
169 EXPECT(path2.starts_with("/tmp/test.mkstemps.prefix"sv));
170 EXPECT(path2.ends_with("suffix"sv));
171 EXPECT_EQ(strlen(path), path2.length());
172
173 EXPECT_NE(path1, path2);
174 }
175
176 munmap(ptr, sizeof(*ptr));
177}