12965785mm/*-
22965785mm * Copyright (c) 2003-2007 Tim Kientzle
32965785mm * All rights reserved.
42965785mm *
52965785mm * Redistribution and use in source and binary forms, with or without
62965785mm * modification, are permitted provided that the following conditions
72965785mm * are met:
82965785mm * 1. Redistributions of source code must retain the above copyright
92965785mm *    notice, this list of conditions and the following disclaimer.
102965785mm * 2. Redistributions in binary form must reproduce the above copyright
112965785mm *    notice, this list of conditions and the following disclaimer in the
122965785mm *    documentation and/or other materials provided with the distribution.
132965785mm *
142965785mm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
152965785mm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
162965785mm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
172965785mm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
182965785mm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
192965785mm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
202965785mm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
212965785mm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
222965785mm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
232965785mm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
242965785mm */
252965785mm#include "test.h"
265fa2c01mm__FBSDID("$FreeBSD$");
272965785mm
282965785mmstatic void
292965785mmverify_files(const char *msg)
302965785mm{
312965785mm	/*
322965785mm	 * Verify unpacked files.
332965785mm	 */
342965785mm
352965785mm	/* Regular file with 2 links. */
361c0c7f8mm	failure("%s", msg);
372965785mm	assertIsReg("file", 0644);
381c0c7f8mm	failure("%s", msg);
392965785mm	assertFileSize("file", 10);
401c0c7f8mm	failure("%s", msg);
412965785mm	assertFileNLinks("file", 2);
422965785mm
432965785mm	/* Another name for the same file. */
441c0c7f8mm	failure("%s", msg);
452965785mm	assertIsHardlink("linkfile", "file");
462965785mm
472965785mm	/* Symlink */
482965785mm	if (canSymlink())
49e9183e3mm		assertIsSymlink("symlink", "file", 0);
502965785mm
512965785mm	/* Another file with 1 link and different permissions. */
521c0c7f8mm	failure("%s", msg);
532965785mm	assertIsReg("file2", 0777);
541c0c7f8mm	failure("%s", msg);
552965785mm	assertFileSize("file2", 10);
561c0c7f8mm	failure("%s", msg);
572965785mm	assertFileNLinks("file2", 1);
582965785mm
592965785mm	/* dir */
602965785mm	assertIsDir("dir", 0775);
612965785mm}
622965785mm
632965785mmstatic void
642965785mmbasic_cpio(const char *target,
652965785mm    const char *pack_options,
662965785mm    const char *unpack_options,
672f6e434mm    const char *se, const char *se2)
682965785mm{
692965785mm	int r;
702965785mm
712965785mm	if (!assertMakeDir(target, 0775))
722965785mm	    return;
732965785mm
742965785mm	/* Use the cpio program to create an archive. */
753404e2cmm	r = systemf("%s -R 1000:1000 -o %s < filelist >%s/archive 2>%s/pack.err",
762965785mm	    testprog, pack_options, target, target);
772965785mm	failure("Error invoking %s -o %s", testprog, pack_options);
782965785mm	assertEqualInt(r, 0);
792965785mm
802965785mm	assertChdir(target);
812965785mm
822965785mm	/* Verify stderr. */
832965785mm	failure("Expected: %s, options=%s", se, pack_options);
842965785mm	assertTextFileContents(se, "pack.err");
852965785mm
862965785mm	/*
872965785mm	 * Use cpio to unpack the archive into another directory.
882965785mm	 */
892965785mm	r = systemf("%s -i %s< archive >unpack.out 2>unpack.err",
902965785mm	    testprog, unpack_options);
912965785mm	failure("Error invoking %s -i %s", testprog, unpack_options);
922965785mm	assertEqualInt(r, 0);
932965785mm
942965785mm	/* Verify stderr. */
952965785mm	failure("Error invoking %s -i %s in dir %s", testprog, unpack_options, target);
962f6e434mm	assertTextFileContents(se2, "unpack.err");
972965785mm
982965785mm	verify_files(pack_options);
992965785mm
1002965785mm	assertChdir("..");
1012965785mm}
1022965785mm
1032965785mmstatic void
1042965785mmpassthrough(const char *target)
1052965785mm{
1062965785mm	int r;
1072965785mm
1082965785mm	if (!assertMakeDir(target, 0775))
1092965785mm		return;
1102965785mm
1112965785mm	/*
1122965785mm	 * Use cpio passthrough mode to copy files to another directory.
1132965785mm	 */
1142965785mm	r = systemf("%s -p %s <filelist >%s/stdout 2>%s/stderr",
1152965785mm	    testprog, target, target, target);
1162965785mm	failure("Error invoking %s -p", testprog);
1172965785mm	assertEqualInt(r, 0);
1182965785mm
1192965785mm	assertChdir(target);
1202965785mm
1212965785mm	/* Verify stderr. */
1222965785mm	failure("Error invoking %s -p in dir %s",
1232965785mm	    testprog, target);
1242965785mm	assertTextFileContents("1 block\n", "stderr");
1252965785mm
1262965785mm	verify_files("passthrough");
1272965785mm	assertChdir("..");
1282965785mm}
1292965785mm
1302965785mmDEFINE_TEST(test_basic)
1312965785mm{
1322965785mm	FILE *filelist;
1332965785mm	const char *msg;
1342f6e434mm	char result[1024];
1352965785mm
1362965785mm	assertUmask(0);
1372965785mm
1382965785mm	/*
1392965785mm	 * Create an assortment of files on disk.
1402965785mm	 */
1412965785mm	filelist = fopen("filelist", "w");
1422f6e434mm	memset(result, 0, sizeof(result));
1432965785mm
1442965785mm	/* File with 10 bytes content. */
1452965785mm	assertMakeFile("file", 0644, "1234567890");
1462965785mm	fprintf(filelist, "file\n");
147afd649dmm	if (is_LargeInode("file")) {
1482f6e434mm		strncat(result,
149afd649dmm		    "bsdcpio: file: large inode number truncated: ",
150366f427mm		    sizeof(result) - strlen(result) -1);
151afd649dmm		strncat(result,
152afd649dmm		    strerror(ERANGE),
153afd649dmm		    sizeof(result) - strlen(result) -1);
154afd649dmm		strncat(result,
155afd649dmm		    "\n",
156afd649dmm		    sizeof(result) - strlen(result) -1);
157afd649dmm	}
1582965785mm
1592965785mm	/* hardlink to above file. */
1602965785mm	assertMakeHardlink("linkfile", "file");
1612965785mm	fprintf(filelist, "linkfile\n");
162afd649dmm	if (is_LargeInode("linkfile")) {
163afd649dmm		strncat(result,
164afd649dmm		    "bsdcpio: linkfile: large inode number truncated: ",
165afd649dmm		    sizeof(result) - strlen(result) -1);
166afd649dmm		strncat(result,
167afd649dmm		    strerror(ERANGE),
168afd649dmm		    sizeof(result) - strlen(result) -1);
1692f6e434mm		strncat(result,
170afd649dmm		    "\n",
171366f427mm		    sizeof(result) - strlen(result) -1);
172afd649dmm	}
1732965785mm
1742965785mm	/* Symlink to above file. */
1752965785mm	if (canSymlink()) {
176e9183e3mm		assertMakeSymlink("symlink", "file", 0);
1772965785mm		fprintf(filelist, "symlink\n");
178afd649dmm		if (is_LargeInode("symlink")) {
179afd649dmm			strncat(result,
180afd649dmm			    "bsdcpio: symlink: large inode number truncated: ",
181afd649dmm			    sizeof(result) - strlen(result) -1);
1822f6e434mm			strncat(result,
183afd649dmm			    strerror(ERANGE),
184366f427mm			    sizeof(result) - strlen(result) -1);
185afd649dmm			strncat(result,
186afd649dmm			    "\n",
187afd649dmm			    sizeof(result) - strlen(result) -1);
188afd649dmm		}
1892965785mm	}
1902965785mm
1912965785mm	/* Another file with different permissions. */
1922965785mm	assertMakeFile("file2", 0777, "1234567890");
1932965785mm	fprintf(filelist, "file2\n");
194afd649dmm	if (is_LargeInode("file2")) {
195afd649dmm		strncat(result,
196afd649dmm		    "bsdcpio: file2: large inode number truncated: ",
197afd649dmm		    sizeof(result) - strlen(result) -1);
198afd649dmm		strncat(result,
199afd649dmm		    strerror(ERANGE),
200afd649dmm		    sizeof(result) - strlen(result) -1);
2012f6e434mm		strncat(result,
202afd649dmm		    "\n",
203366f427mm		    sizeof(result) - strlen(result) -1);
204afd649dmm	}
2052965785mm
2062965785mm	/* Directory. */
2072965785mm	assertMakeDir("dir", 0775);
2082965785mm	fprintf(filelist, "dir\n");
209afd649dmm	if (is_LargeInode("dir")) {
210afd649dmm		strncat(result,
211afd649dmm		    "bsdcpio: dir: large inode number truncated: ",
212afd649dmm		    sizeof(result) - strlen(result) -1);
2132f6e434mm		strncat(result,
214afd649dmm		    strerror(ERANGE),
215366f427mm		    sizeof(result) - strlen(result) -1);
216afd649dmm		strncat(result,
217afd649dmm		    "\n",
218afd649dmm		    sizeof(result) - strlen(result) -1);
219afd649dmm	}
220366f427mm	strncat(result, "2 blocks\n", sizeof(result) - strlen(result) -1);
2212f6e434mm
2222965785mm	/* All done. */
2232965785mm	fclose(filelist);
2242965785mm
2252965785mm	assertUmask(022);
2262965785mm
2272965785mm	/* Archive/dearchive with a variety of options. */
2282965785mm	msg = canSymlink() ? "2 blocks\n" : "1 block\n";
2292f6e434mm	basic_cpio("copy", "", "", msg, msg);
2302f6e434mm	basic_cpio("copy_odc", "--format=odc", "", msg, msg);
2312f6e434mm	basic_cpio("copy_newc", "-H newc", "", result, "2 blocks\n");
2322f6e434mm	basic_cpio("copy_cpio", "-H odc", "", msg, msg);
2332965785mm	msg = canSymlink() ? "9 blocks\n" : "8 blocks\n";
2342f6e434mm	basic_cpio("copy_ustar", "-H ustar", "", msg, msg);
2352965785mm
2362965785mm	/* Copy in one step using -p */
2372965785mm	passthrough("passthrough");
2382965785mm}
239