]> git.proxmox.com Git - mirror_lxc.git/blame - src/tests/lxc-test-utils.c
utils: add lxc_safe_long_long()
[mirror_lxc.git] / src / tests / lxc-test-utils.c
CommitLineData
bed0d08f
CB
1/*
2 * lxc: linux Container library
3 *
4 * Copyright © 2016 Canonical Ltd.
5 *
6 * Authors:
7 * Christian Brauner <christian.brauner@mailbox.org>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
1a514c15 24#define _GNU_SOURCE
cb9df6d4 25#define __STDC_FORMAT_MACROS
24b9970e
CB
26#include <errno.h>
27#include <fcntl.h>
cb9df6d4 28#include <inttypes.h>
57c7adc3 29#include <limits.h>
cb9df6d4 30#include <sched.h>
bed0d08f
CB
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
24b9970e
CB
34#include <unistd.h>
35#include <sys/mount.h>
36#include <sys/stat.h>
37#include <sys/types.h>
bed0d08f
CB
38
39#include "lxctest.h"
40#include "utils.h"
41
1a514c15
CB
42void test_lxc_deslashify(void)
43{
eda0afd4
CB
44 char *s = "/A///B//C/D/E/";
45 char *t;
46
47 t = lxc_deslashify(s);
48 if (!t)
1a514c15 49 exit(EXIT_FAILURE);
eda0afd4
CB
50 lxc_test_assert_abort(strcmp(t, "/A/B/C/D/E") == 0);
51 free(t);
52
53 s = "/A";
1a514c15 54
eda0afd4
CB
55 t = lxc_deslashify(s);
56 if (!t)
1a514c15 57 exit(EXIT_FAILURE);
eda0afd4
CB
58 lxc_test_assert_abort(strcmp(t, "/A") == 0);
59 free(t);
1a514c15 60
eda0afd4
CB
61 s = "";
62 t = lxc_deslashify(s);
63 if (!t)
1a514c15 64 exit(EXIT_FAILURE);
eda0afd4
CB
65 lxc_test_assert_abort(strcmp(t, "") == 0);
66 free(t);
67
68 s = "//";
1a514c15 69
eda0afd4
CB
70 t = lxc_deslashify(s);
71 if (!t)
1a514c15 72 exit(EXIT_FAILURE);
eda0afd4
CB
73 lxc_test_assert_abort(strcmp(t, "/") == 0);
74 free(t);
1a514c15
CB
75}
76
de3c491b 77/* /proc/int_as_str/ns/mnt\0 = (5 + 21 + 7 + 1) */
eab15c1e 78#define __MNTNS_LEN (5 + (LXC_NUMSTRLEN64) + 7 + 1)
24b9970e
CB
79void test_detect_ramfs_rootfs(void)
80{
81 size_t i;
82 int ret;
83 int fret = EXIT_FAILURE;
de3c491b 84 char path[__MNTNS_LEN];
24b9970e
CB
85 int init_ns = -1;
86 char tmpf1[] = "lxc-test-utils-XXXXXX";
87 char tmpf2[] = "lxc-test-utils-XXXXXX";
88 int fd1 = -1, fd2 = -1;
89 FILE *fp1 = NULL, *fp2 = NULL;
90 char *mountinfo[] = {
91 "18 24 0:17 / /sys rw,nosuid,nodev,noexec,relatime shared:7 - sysfs sysfs rw",
92 "19 24 0:4 / /proc rw,nosuid,nodev,noexec,relatime shared:13 - proc proc rw",
93 "20 24 0:6 / /dev rw,nosuid,relatime shared:2 - devtmpfs udev rw,size=4019884k,nr_inodes=1004971,mode=755",
94 "21 20 0:14 / /dev/pts rw,nosuid,noexec,relatime shared:3 - devpts devpts rw,gid=5,mode=620,ptmxmode=000",
95 "22 24 0:18 / /run rw,nosuid,noexec,relatime shared:5 - tmpfs tmpfs rw,size=807912k,mode=755",
96
97 /* This is what we care about. */
98 "24 0 8:2 / / rw - rootfs rootfs rw,size=1004396k,nr_inodes=251099",
99
100 "25 18 0:12 / /sys/kernel/security rw,nosuid,nodev,noexec,relatime shared:8 - securityfs securityfs rw",
101 "26 20 0:20 / /dev/shm rw,nosuid,nodev shared:4 - tmpfs tmpfs rw",
102 "27 22 0:21 / /run/lock rw,nosuid,nodev,noexec,relatime shared:6 - tmpfs tmpfs rw,size=5120k",
103 "28 18 0:22 / /sys/fs/cgroup ro,nosuid,nodev,noexec shared:9 - tmpfs tmpfs ro,mode=755",
104 "29 28 0:23 / /sys/fs/cgroup/systemd rw,nosuid,nodev,noexec,relatime shared:10 - cgroup cgroup rw,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd",
105 "30 18 0:24 / /sys/fs/pstore rw,nosuid,nodev,noexec,relatime shared:11 - pstore pstore rw",
106 "31 18 0:25 / /sys/firmware/efi/efivars rw,nosuid,nodev,noexec,relatime shared:12 - efivarfs efivarfs rw",
107 "32 28 0:26 / /sys/fs/cgroup/cpu,cpuacct rw,nosuid,nodev,noexec,relatime shared:14 - cgroup cgroup rw,cpu,cpuacct",
108 "33 28 0:27 / /sys/fs/cgroup/net_cls,net_prio rw,nosuid,nodev,noexec,relatime shared:15 - cgroup cgroup rw,net_cls,net_prio",
109 "34 28 0:28 / /sys/fs/cgroup/blkio rw,nosuid,nodev,noexec,relatime shared:16 - cgroup cgroup rw,blkio",
110 "35 28 0:29 / /sys/fs/cgroup/freezer rw,nosuid,nodev,noexec,relatime shared:17 - cgroup cgroup rw,freezer",
111 "36 28 0:30 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime shared:18 - cgroup cgroup rw,memory",
112 "37 28 0:31 / /sys/fs/cgroup/hugetlb rw,nosuid,nodev,noexec,relatime shared:19 - cgroup cgroup rw,hugetlb",
113 "38 28 0:32 / /sys/fs/cgroup/cpuset rw,nosuid,nodev,noexec,relatime shared:20 - cgroup cgroup rw,cpuset",
114 "39 28 0:33 / /sys/fs/cgroup/devices rw,nosuid,nodev,noexec,relatime shared:21 - cgroup cgroup rw,devices",
115 "40 28 0:34 / /sys/fs/cgroup/pids rw,nosuid,nodev,noexec,relatime shared:22 - cgroup cgroup rw,pids",
116 "41 28 0:35 / /sys/fs/cgroup/perf_event rw,nosuid,nodev,noexec,relatime shared:23 - cgroup cgroup rw,perf_event",
117 "42 19 0:36 / /proc/sys/fs/binfmt_misc rw,relatime shared:24 - autofs systemd-1 rw,fd=32,pgrp=1,timeout=0,minproto=5,maxproto=5,direct",
118 "43 18 0:7 / /sys/kernel/debug rw,relatime shared:25 - debugfs debugfs rw",
119 "44 20 0:37 / /dev/hugepages rw,relatime shared:26 - hugetlbfs hugetlbfs rw",
120 "45 20 0:16 / /dev/mqueue rw,relatime shared:27 - mqueue mqueue rw",
121 "46 43 0:9 / /sys/kernel/debug/tracing rw,relatime shared:28 - tracefs tracefs rw",
122 "76 18 0:38 / /sys/fs/fuse/connections rw,relatime shared:29 - fusectl fusectl rw",
123 "78 24 8:1 / /boot/efi rw,relatime shared:30 - vfat /dev/sda1 rw,fmask=0077,dmask=0077,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro",
124 };
125
de3c491b
CB
126 ret = snprintf(path, __MNTNS_LEN, "/proc/self/ns/mnt");
127 if (ret < 0 || (size_t)ret >= __MNTNS_LEN) {
24b9970e
CB
128 lxc_error("%s\n", "Failed to create path with snprintf().");
129 goto non_test_error;
130 }
131
132 init_ns = open(path, O_RDONLY | O_CLOEXEC);
133 if (init_ns < 0) {
134 lxc_error("%s\n", "Failed to open initial mount namespace.");
135 goto non_test_error;
136 }
137
138 if (unshare(CLONE_NEWNS) < 0) {
139 lxc_error("%s\n", "Could not unshare mount namespace.");
140 close(init_ns);
141 init_ns = -1;
142 goto non_test_error;
143 }
144
145 if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0) < 0) {
146 lxc_error("Failed to remount / private: %s.\n", strerror(errno));
147 goto non_test_error;
148 }
149
150 fd1 = mkstemp(tmpf1);
151 if (fd1 < 0) {
152 lxc_error("%s\n", "Could not create temporary file.");
153 goto non_test_error;
154 }
155
156 fd2 = mkstemp(tmpf2);
157 if (fd2 < 0) {
158 lxc_error("%s\n", "Could not create temporary file.");
159 goto non_test_error;
160 }
161
162 fp1 = fdopen(fd1, "r+");
163 if (!fp1) {
164 lxc_error("%s\n", "Could not fdopen() temporary file.");
165 goto non_test_error;
166 }
167
168 fp2 = fdopen(fd2, "r+");
169 if (!fp2) {
170 lxc_error("%s\n", "Could not fdopen() temporary file.");
171 goto non_test_error;
172 }
173
174 /* Test if it correctly detects - rootfs rootfs */
175 for (i = 0; i < sizeof(mountinfo) / sizeof(mountinfo[0]); i++) {
176 if (fprintf(fp1, "%s\n", mountinfo[i]) < 0) {
177 lxc_error("Could not write \"%s\" to temporary file.", mountinfo[i]);
178 goto non_test_error;
179 }
180 }
181 fclose(fp1);
182 fp1 = NULL;
183
184 /* Test if it correctly fails to detect when no - rootfs rootfs */
185 for (i = 0; i < sizeof(mountinfo) / sizeof(mountinfo[0]); i++) {
186 if (strcmp(mountinfo[i], "24 0 8:2 / / rw - rootfs rootfs rw,size=1004396k,nr_inodes=251099") == 0)
187 continue;
188 if (fprintf(fp2, "%s\n", mountinfo[i]) < 0) {
189 lxc_error("Could not write \"%s\" to temporary file.", mountinfo[i]);
190 goto non_test_error;
191 }
192 }
193 fclose(fp2);
194 fp2 = NULL;
195
196 if (mount(tmpf1, "/proc/self/mountinfo", NULL, MS_BIND, 0) < 0) {
197 lxc_error("%s\n", "Could not overmount \"/proc/self/mountinfo\".");
198 goto non_test_error;
199 }
200
201 lxc_test_assert_abort(detect_ramfs_rootfs());
202
203 if (mount(tmpf2, "/proc/self/mountinfo", NULL, MS_BIND, 0) < 0) {
204 lxc_error("%s\n", "Could not overmount \"/proc/self/mountinfo\".");
205 goto non_test_error;
206 }
207
208 lxc_test_assert_abort(!detect_ramfs_rootfs());
209 fret = EXIT_SUCCESS;
210
211non_test_error:
212 if (fp1)
213 fclose(fp1);
214 else if (fd1 > 0)
215 close(fd1);
216 if (fp2)
217 fclose(fp2);
218 else if (fd2 > 0)
219 close(fd2);
220
221 if (init_ns > 0) {
222 if (setns(init_ns, 0) < 0) {
223 lxc_error("Failed to switch back to initial mount namespace: %s.\n", strerror(errno));
224 fret = EXIT_FAILURE;
225 }
226 close(init_ns);
227 }
228 if (fret == EXIT_SUCCESS)
229 return;
230 exit(fret);
aa75cefc 231}
57c7adc3
CB
232
233void test_lxc_safe_uint(void)
234{
15fe2189 235 int ret;
57c7adc3 236 unsigned int n;
15fe2189
CB
237 char numstr[LXC_NUMSTRLEN64];
238
239 lxc_test_assert_abort((-EINVAL == lxc_safe_uint(" -123", &n)));
240 lxc_test_assert_abort((-EINVAL == lxc_safe_uint("-123", &n)));
241
242 ret = snprintf(numstr, LXC_NUMSTRLEN64, "%" PRIu64, (uint64_t)UINT_MAX);
243 if (ret < 0 || ret >= LXC_NUMSTRLEN64)
244 exit(EXIT_FAILURE);
245 lxc_test_assert_abort((0 == lxc_safe_uint(numstr, &n)) && n == UINT_MAX);
246
247 ret = snprintf(numstr, LXC_NUMSTRLEN64, "%" PRIu64, (uint64_t)UINT_MAX + 1);
248 if (ret < 0 || ret >= LXC_NUMSTRLEN64)
249 exit(EXIT_FAILURE);
250 lxc_test_assert_abort((-ERANGE == lxc_safe_uint(numstr, &n)));
57c7adc3
CB
251
252 lxc_test_assert_abort((0 == lxc_safe_uint("1234345", &n)) && n == 1234345);
253 lxc_test_assert_abort((0 == lxc_safe_uint(" 345", &n)) && n == 345);
254 lxc_test_assert_abort((-EINVAL == lxc_safe_uint(" g345", &n)));
255 lxc_test_assert_abort((-EINVAL == lxc_safe_uint(" 3g45", &n)));
256 lxc_test_assert_abort((-EINVAL == lxc_safe_uint(" 345g", &n)));
257 lxc_test_assert_abort((-EINVAL == lxc_safe_uint("g345", &n)));
258 lxc_test_assert_abort((-EINVAL == lxc_safe_uint("3g45", &n)));
259 lxc_test_assert_abort((-EINVAL == lxc_safe_uint("345g", &n)));
260 lxc_test_assert_abort((-EINVAL == lxc_safe_uint("g345 ", &n)));
261 lxc_test_assert_abort((-EINVAL == lxc_safe_uint("3g45 ", &n)));
262 lxc_test_assert_abort((-EINVAL == lxc_safe_uint("345g ", &n)));
263 lxc_test_assert_abort((-EINVAL == lxc_safe_uint("g", &n)));
264 lxc_test_assert_abort((-EINVAL == lxc_safe_uint(" g345", &n)));
24b9970e
CB
265}
266
aa75cefc
CB
267void test_lxc_safe_int(void)
268{
15fe2189 269 int ret;
aa75cefc 270 signed int n;
15fe2189
CB
271 char numstr[LXC_NUMSTRLEN64];
272
273 ret = snprintf(numstr, LXC_NUMSTRLEN64, "%" PRIu64, (uint64_t)INT_MAX);
274 if (ret < 0 || ret >= LXC_NUMSTRLEN64)
275 exit(EXIT_FAILURE);
276 lxc_test_assert_abort((0 == lxc_safe_int(numstr, &n)) && n == INT_MAX);
277
278 ret = snprintf(numstr, LXC_NUMSTRLEN64, "%" PRIu64, (uint64_t)INT_MAX + 1);
279 if (ret < 0 || ret >= LXC_NUMSTRLEN64)
280 exit(EXIT_FAILURE);
281 lxc_test_assert_abort((-ERANGE == lxc_safe_int(numstr, &n)));
282
283 ret = snprintf(numstr, LXC_NUMSTRLEN64, "%" PRId64, (int64_t)INT_MIN);
284 if (ret < 0 || ret >= LXC_NUMSTRLEN64)
285 exit(EXIT_FAILURE);
286 lxc_test_assert_abort((0 == lxc_safe_int(numstr, &n)) && n == INT_MIN);
287
288 ret = snprintf(numstr, LXC_NUMSTRLEN64, "%" PRId64, (int64_t)INT_MIN - 1);
289 if (ret < 0 || ret >= LXC_NUMSTRLEN64)
290 exit(EXIT_FAILURE);
291 lxc_test_assert_abort((-ERANGE == lxc_safe_int(numstr, &n)));
aa75cefc
CB
292
293 lxc_test_assert_abort((0 == lxc_safe_int("1234345", &n)) && n == 1234345);
294 lxc_test_assert_abort((0 == lxc_safe_int(" 345", &n)) && n == 345);
295 lxc_test_assert_abort((0 == lxc_safe_int("-1234345", &n)) && n == -1234345);
296 lxc_test_assert_abort((0 == lxc_safe_int(" -345", &n)) && n == -345);
297 lxc_test_assert_abort((-EINVAL == lxc_safe_int(" g345", &n)));
298 lxc_test_assert_abort((-EINVAL == lxc_safe_int(" 3g45", &n)));
299 lxc_test_assert_abort((-EINVAL == lxc_safe_int(" 345g", &n)));
300 lxc_test_assert_abort((-EINVAL == lxc_safe_int("g345", &n)));
301 lxc_test_assert_abort((-EINVAL == lxc_safe_int("3g45", &n)));
302 lxc_test_assert_abort((-EINVAL == lxc_safe_int("345g", &n)));
303 lxc_test_assert_abort((-EINVAL == lxc_safe_int("g345 ", &n)));
304 lxc_test_assert_abort((-EINVAL == lxc_safe_int("3g45 ", &n)));
305 lxc_test_assert_abort((-EINVAL == lxc_safe_int("345g ", &n)));
306 lxc_test_assert_abort((-EINVAL == lxc_safe_int("g", &n)));
307 lxc_test_assert_abort((-EINVAL == lxc_safe_int(" g345", &n)));
aa75cefc
CB
308}
309
cb9df6d4
CB
310void test_lxc_safe_long(void)
311{
cb9df6d4 312 signed long int n;
cb9df6d4
CB
313
314 lxc_test_assert_abort((0 == lxc_safe_long("1234345", &n)) && n == 1234345);
315 lxc_test_assert_abort((0 == lxc_safe_long(" 345", &n)) && n == 345);
316 lxc_test_assert_abort((0 == lxc_safe_long("-1234345", &n)) && n == -1234345);
317 lxc_test_assert_abort((0 == lxc_safe_long(" -345", &n)) && n == -345);
318 lxc_test_assert_abort((-EINVAL == lxc_safe_long(" g345", &n)));
319 lxc_test_assert_abort((-EINVAL == lxc_safe_long(" 3g45", &n)));
320 lxc_test_assert_abort((-EINVAL == lxc_safe_long(" 345g", &n)));
321 lxc_test_assert_abort((-EINVAL == lxc_safe_long("g345", &n)));
322 lxc_test_assert_abort((-EINVAL == lxc_safe_long("3g45", &n)));
323 lxc_test_assert_abort((-EINVAL == lxc_safe_long("345g", &n)));
324 lxc_test_assert_abort((-EINVAL == lxc_safe_long("g345 ", &n)));
325 lxc_test_assert_abort((-EINVAL == lxc_safe_long("3g45 ", &n)));
326 lxc_test_assert_abort((-EINVAL == lxc_safe_long("345g ", &n)));
327 lxc_test_assert_abort((-EINVAL == lxc_safe_long("g", &n)));
328 lxc_test_assert_abort((-EINVAL == lxc_safe_long(" g345", &n)));
cb9df6d4
CB
329}
330
29c57e4e 331void test_lxc_string_replace(void)
bed0d08f
CB
332{
333 char *s;
334
335 s = lxc_string_replace("A", "A", "A");
336 lxc_test_assert_abort(strcmp(s, "A") == 0);
337 free(s);
338
339 s = lxc_string_replace("A", "AA", "A");
340 lxc_test_assert_abort(strcmp(s, "AA") == 0);
341 free(s);
342
343 s = lxc_string_replace("A", "AA", "BA");
344 lxc_test_assert_abort(strcmp(s, "BAA") == 0);
345 free(s);
346
347 s = lxc_string_replace("A", "AA", "BAB");
348 lxc_test_assert_abort(strcmp(s, "BAAB") == 0);
349 free(s);
350
351 s = lxc_string_replace("AA", "A", "AA");
352 lxc_test_assert_abort(strcmp(s, "A") == 0);
353 free(s);
354
355 s = lxc_string_replace("AA", "A", "BAA");
356 lxc_test_assert_abort(strcmp(s, "BA") == 0);
357 free(s);
358
359 s = lxc_string_replace("AA", "A", "BAAB");
360 lxc_test_assert_abort(strcmp(s, "BAB") == 0);
361 free(s);
362
363 s = lxc_string_replace("\"A\"A", "\"A\"", "B\"A\"AB");
364 lxc_test_assert_abort(strcmp(s, "B\"A\"B") == 0);
365 free(s);
366}
367
29c57e4e
CB
368void test_lxc_string_in_array(void)
369{
370 lxc_test_assert_abort(lxc_string_in_array("", (const char *[]){"", NULL}));
371 lxc_test_assert_abort(!lxc_string_in_array("A", (const char *[]){"", NULL}));
372 lxc_test_assert_abort(!lxc_string_in_array("AAA", (const char *[]){"", "3472", "jshH", NULL}));
373
374 lxc_test_assert_abort(lxc_string_in_array("A", (const char *[]){"A", NULL}));
375 lxc_test_assert_abort(lxc_string_in_array("A", (const char *[]){"A", "B", "C", NULL}));
376 lxc_test_assert_abort(lxc_string_in_array("A", (const char *[]){"B", "A", "C", NULL}));
377
378 lxc_test_assert_abort(lxc_string_in_array("ABC", (const char *[]){"ASD", "ATR", "ABC", NULL}));
379 lxc_test_assert_abort(lxc_string_in_array("GHJ", (const char *[]){"AZIU", "WRT567B", "879C", "GHJ", "IUZ89", NULL}));
380 lxc_test_assert_abort(lxc_string_in_array("XYZ", (const char *[]){"BERTA", "ARQWE(9", "C8Zhkd", "7U", "XYZ", "UOIZ9", "=)()", NULL}));
381}
382
bed0d08f
CB
383int main(int argc, char *argv[])
384{
29c57e4e
CB
385 test_lxc_string_replace();
386 test_lxc_string_in_array();
1a514c15 387 test_lxc_deslashify();
24b9970e 388 test_detect_ramfs_rootfs();
57c7adc3 389 test_lxc_safe_uint();
aa75cefc 390 test_lxc_safe_int();
cb9df6d4 391 test_lxc_safe_long();
bed0d08f
CB
392
393 exit(EXIT_SUCCESS);
394}