1228753Smm/*-
2228753Smm * Copyright (c) 2003-2007 Tim Kientzle
3228753Smm * All rights reserved.
4228753Smm *
5228753Smm * Redistribution and use in source and binary forms, with or without
6228753Smm * modification, are permitted provided that the following conditions
7228753Smm * are met:
8228753Smm * 1. Redistributions of source code must retain the above copyright
9228753Smm *    notice, this list of conditions and the following disclaimer.
10228753Smm * 2. Redistributions in binary form must reproduce the above copyright
11228753Smm *    notice, this list of conditions and the following disclaimer in the
12228753Smm *    documentation and/or other materials provided with the distribution.
13228753Smm *
14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24228753Smm */
25228753Smm#include "test.h"
26228763Smm__FBSDID("$FreeBSD: stable/11/contrib/libarchive/libarchive/test/test_read_extract.c 358088 2020-02-19 01:50:47Z mm $");
27228753Smm
28228753Smm#define BUFF_SIZE 1000000
29228753Smm#define FILE_BUFF_SIZE 100000
30228753Smm
31228753SmmDEFINE_TEST(test_read_extract)
32228753Smm{
33228753Smm	struct archive_entry *ae;
34228753Smm	struct archive *a;
35228753Smm	size_t used;
36228753Smm	int i, numEntries = 0;
37228753Smm	char *buff, *file_buff;
38228753Smm
39228753Smm	buff = malloc(BUFF_SIZE);
40228753Smm	file_buff = malloc(FILE_BUFF_SIZE);
41228753Smm
42228753Smm	/* Force the umask to something predictable. */
43228753Smm	assertUmask(022);
44228753Smm
45228753Smm	/* Create a new archive in memory containing various types of entries. */
46228753Smm	assert((a = archive_write_new()) != NULL);
47228753Smm	assertA(0 == archive_write_set_format_ustar(a));
48248616Smm	assertA(0 == archive_write_add_filter_none(a));
49228753Smm	assertA(0 == archive_write_open_memory(a, buff, BUFF_SIZE, &used));
50228753Smm	/* A directory to be restored with EXTRACT_PERM. */
51228753Smm	++numEntries;
52228753Smm	assert((ae = archive_entry_new()) != NULL);
53228753Smm	archive_entry_copy_pathname(ae, "dir_0775");
54228753Smm	archive_entry_set_mode(ae, S_IFDIR | 0775);
55228753Smm	assertA(0 == archive_write_header(a, ae));
56228753Smm	archive_entry_free(ae);
57228753Smm	/* A regular file. */
58228753Smm	++numEntries;
59228753Smm	assert((ae = archive_entry_new()) != NULL);
60228753Smm	archive_entry_copy_pathname(ae, "file");
61228753Smm	archive_entry_set_mode(ae, S_IFREG | 0755);
62228753Smm	for (i = 0; i < FILE_BUFF_SIZE; i++)
63228753Smm		file_buff[i] = (unsigned char)rand();
64228753Smm	archive_entry_set_size(ae, FILE_BUFF_SIZE);
65228753Smm	assertA(0 == archive_write_header(a, ae));
66228753Smm	assertA(FILE_BUFF_SIZE == archive_write_data(a, file_buff, FILE_BUFF_SIZE));
67228753Smm	archive_entry_free(ae);
68228753Smm	/* A directory that should obey umask when restored. */
69228753Smm	++numEntries;
70228753Smm	assert((ae = archive_entry_new()) != NULL);
71228753Smm	archive_entry_copy_pathname(ae, "dir");
72228753Smm	archive_entry_set_mode(ae, S_IFDIR | 0777);
73228753Smm	assertA(0 == archive_write_header(a, ae));
74228753Smm	archive_entry_free(ae);
75228753Smm	/* A file in the directory. */
76228753Smm	++numEntries;
77228753Smm	assert((ae = archive_entry_new()) != NULL);
78228753Smm	archive_entry_copy_pathname(ae, "dir/file");
79228753Smm	archive_entry_set_mode(ae, S_IFREG | 0700);
80228753Smm	assertA(0 == archive_write_header(a, ae));
81228753Smm	archive_entry_free(ae);
82228753Smm	/* A file in a dir that is not already in the archive. */
83228753Smm	++numEntries;
84228753Smm	assert((ae = archive_entry_new()) != NULL);
85228753Smm	archive_entry_copy_pathname(ae, "dir2/file");
86228753Smm	archive_entry_set_mode(ae, S_IFREG | 0000);
87228753Smm	assertA(0 == archive_write_header(a, ae));
88228753Smm	archive_entry_free(ae);
89228753Smm	/* A dir with a trailing /. */
90228753Smm	++numEntries;
91228753Smm	assert((ae = archive_entry_new()) != NULL);
92228753Smm	archive_entry_copy_pathname(ae, "dir3/.");
93228753Smm	archive_entry_set_mode(ae, S_IFDIR | 0710);
94228753Smm	assertA(0 == archive_write_header(a, ae));
95228753Smm	archive_entry_free(ae);
96228753Smm	/* Multiple dirs with a single entry. */
97228753Smm	++numEntries;
98228753Smm	assert((ae = archive_entry_new()) != NULL);
99228753Smm	archive_entry_copy_pathname(ae, "dir4/a/../b/../c/");
100228753Smm	archive_entry_set_mode(ae, S_IFDIR | 0711);
101228753Smm	assertA(0 == archive_write_header(a, ae));
102228753Smm	archive_entry_free(ae);
103228753Smm	/* A symlink. */
104228753Smm	if (canSymlink()) {
105228753Smm		++numEntries;
106228753Smm		assert((ae = archive_entry_new()) != NULL);
107228753Smm		archive_entry_copy_pathname(ae, "symlink");
108228753Smm		archive_entry_set_mode(ae, AE_IFLNK | 0755);
109228753Smm		archive_entry_set_symlink(ae, "file");
110228753Smm		assertA(0 == archive_write_header(a, ae));
111228753Smm		archive_entry_free(ae);
112228753Smm	}
113228753Smm	/* Close out the archive. */
114232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
115232153Smm	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
116228753Smm
117228753Smm	/* Extract the entries to disk. */
118228753Smm	assert((a = archive_read_new()) != NULL);
119228753Smm	assertA(0 == archive_read_support_format_all(a));
120232153Smm	assertA(0 == archive_read_support_filter_all(a));
121228753Smm	assertA(0 == archive_read_open_memory(a, buff, BUFF_SIZE));
122228753Smm	/* Restore first entry with _EXTRACT_PERM. */
123358088Smm	failure("Error reading first entry");
124228753Smm	assertA(0 == archive_read_next_header(a, &ae));
125228753Smm	assertA(0 == archive_read_extract(a, ae, ARCHIVE_EXTRACT_PERM));
126228753Smm	/* Rest of entries get restored with no flags. */
127228753Smm	for (i = 1; i < numEntries; i++) {
128228753Smm		failure("Error reading entry %d", i);
129228753Smm		assertA(0 == archive_read_next_header(a, &ae));
130228753Smm		failure("Failed to extract entry %d: %s", i,
131228753Smm			archive_entry_pathname(ae));
132228753Smm		assertA(0 == archive_read_extract(a, ae, 0));
133228753Smm	}
134228753Smm	assertA(ARCHIVE_EOF == archive_read_next_header(a, &ae));
135232153Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
136232153Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
137228753Smm
138228753Smm	/* Test the entries on disk. */
139228753Smm	/* This first entry was extracted with ARCHIVE_EXTRACT_PERM,
140228753Smm	 * so the permissions should have been restored exactly,
141228753Smm	 * including resetting the gid bit on those platforms
142228753Smm	 * where gid is inherited by subdirs. */
143228753Smm	failure("This was 0775 in archive, and should be 0775 on disk");
144228753Smm	assertIsDir("dir_0775", 0775);
145228753Smm	/* Everything else was extracted without ARCHIVE_EXTRACT_PERM,
146228753Smm	 * so there may be some sloppiness about gid bits on directories. */
147228753Smm	assertIsReg("file", 0755);
148228753Smm	assertFileSize("file", FILE_BUFF_SIZE);
149228753Smm	assertFileContents(file_buff, FILE_BUFF_SIZE, "file");
150228753Smm	/* If EXTRACT_PERM wasn't used, be careful to ignore sgid bit
151228753Smm	 * when checking dir modes, as some systems inherit sgid bit
152228753Smm	 * from the parent dir. */
153228753Smm	failure("This was 0777 in archive, but umask should make it 0755");
154228753Smm	assertIsDir("dir", 0755);
155228753Smm	assertIsReg("dir/file", 0700);
156228753Smm	assertIsDir("dir2", 0755);
157228753Smm	assertIsReg("dir2/file", 0000);
158228753Smm	assertIsDir("dir3", 0710);
159228753Smm	assertIsDir("dir4", 0755);
160228753Smm	assertIsDir("dir4/a", 0755);
161228753Smm	assertIsDir("dir4/b", 0755);
162228753Smm	assertIsDir("dir4/c", 0711);
163228753Smm	if (canSymlink())
164348607Smm		assertIsSymlink("symlink", "file", 0);
165228753Smm
166228753Smm	free(buff);
167228753Smm	free(file_buff);
168228753Smm}
169