xref: /freebsd/contrib/libarchive/tar/test/test_option_P.c (revision 6c40282284d6eab20256914648cdec39acb2c52a)
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  
DEFINE_TEST(test_extract_tar_absolute_paths)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