xref: /freebsd/contrib/libarchive/tar/test/test_option_P.c (revision 7ab1a32cd43cbae61ad4dd435d6a482bbf61cb52)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2024 Mostyn Bramley-Moore <mostyn@antipode.se>
5  */
6 
7 #include "test.h"
8 
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #if defined(_WIN32) && !defined(__CYGWIN__)
13 #define UNLINK _unlink
14 #else
15 #define UNLINK unlink
16 #endif
17 
18 DEFINE_TEST(test_extract_tar_absolute_paths)
19 {
20 	int r;
21 
22 	// Create an absolute path for a test file inside testworkdir.
23 	char *entry_suffix = "/tar-noabs";
24 	size_t entry_suffix_length = strlen(entry_suffix);
25 	size_t testworkdir_length = strlen(testworkdir);
26 	size_t temp_absolute_file_name_length = testworkdir_length + entry_suffix_length;
27 	char *temp_absolute_file_name = calloc(1, temp_absolute_file_name_length + 1); // +1 for null character.
28 	assertEqualInt(snprintf(temp_absolute_file_name, temp_absolute_file_name_length + 1, "%s%s", testworkdir, entry_suffix),
29 		temp_absolute_file_name_length);
30 
31 #if defined(_WIN32) && !defined(__CYGWIN__)
32 	// I'm unsure how to specify paths with spaces for the test invocation on windows.
33 	// Adding quotes doesn't seem to work. We should find a way to escape these paths,
34 	// but for now let's fail in a place that's obviously related to the test setup if
35 	// testworkdir contains spaces.
36 	for (char *p = temp_absolute_file_name; *p != '\0'; p++)
37 	{
38 		assert(*p != ' ');
39 		if (*p == ' ') break;
40 	}
41 #endif
42 
43 	// Create the file.
44 	const char *sample_data = "test file from test_extract_tar_absolute_paths";
45 	assertMakeFile(temp_absolute_file_name, 0644, sample_data);
46 
47 	// Create an archive with the test file, using an absolute path.
48 #if defined(_WIN32) && !defined(__CYGWIN__)
49 	r = systemf("%s --absolute-paths -cf test.tar %s", testprog, temp_absolute_file_name);
50 #else
51 	r = systemf("%s --absolute-paths -cf test.tar \"%s\"", testprog, temp_absolute_file_name);
52 #endif
53 	assertEqualInt(r, 0);
54 
55 	UNLINK(temp_absolute_file_name);
56 
57 	// Extracting the archive without -P / --absolute-paths should strip leading drive letter or slash
58 	r = systemf("%s -xf test.tar 2>test.err", testprog);
59 	assertEqualInt(r, 0);
60 	assertFileNotExists(temp_absolute_file_name);
61 
62 	// Check that the mangled path exists.
63 #if defined(_WIN32) && !defined(__CYGWIN__)
64 	assertFileExists(temp_absolute_file_name + 3); // Skip the drive letter, colon and slash.
65 	UNLINK(temp_absolute_file_name + 3);
66 #else
67 	assertFileExists(temp_absolute_file_name + 1); // Skip the slash.
68 	UNLINK(temp_absolute_file_name + 1);
69 #endif
70 
71 	// Extracting the archive with -P / --absolute-paths should create the file.
72 	r = systemf("%s --absolute-paths -xf test.tar", testprog);
73 	assertEqualInt(r, 0);
74 	assertFileExists(temp_absolute_file_name);
75 
76 	// Check that the mangled path wasn't created.
77 #if defined(_WIN32) && !defined(__CYGWIN__)
78 	assertFileNotExists(temp_absolute_file_name + 3); // Skip the drive letter, colon and slash.
79 #else
80 	assertFileNotExists(temp_absolute_file_name + 1); // Skip the slash.
81 #endif
82 }
83