1 /*- 2 * Copyright (c) 2003-2007 Tim Kientzle 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 #include "test.h" 26 __FBSDID("$FreeBSD$"); 27 28 static void 29 verify_files(const char *target) 30 { 31 struct stat st, st2; 32 char buff[128]; 33 int r; 34 35 /* 36 * Verify unpacked files. 37 */ 38 39 /* Regular file with 2 links. */ 40 r = lstat("file", &st); 41 failure("Failed to stat file %s/file, errno=%d", target, errno); 42 assertEqualInt(r, 0); 43 if (r == 0) { 44 assert(S_ISREG(st.st_mode)); 45 assertEqualInt(0644, st.st_mode & 0777); 46 assertEqualInt(10, st.st_size); 47 failure("file %s/file should have 2 links", target); 48 assertEqualInt(2, st.st_nlink); 49 } 50 51 /* Another name for the same file. */ 52 r = lstat("linkfile", &st2); 53 failure("Failed to stat file %s/linkfile, errno=%d", target, errno); 54 assertEqualInt(r, 0); 55 if (r == 0) { 56 assert(S_ISREG(st2.st_mode)); 57 assertEqualInt(0644, st2.st_mode & 0777); 58 assertEqualInt(10, st2.st_size); 59 failure("file %s/linkfile should have 2 links", target); 60 assertEqualInt(2, st2.st_nlink); 61 /* Verify that the two are really hardlinked. */ 62 assertEqualInt(st.st_dev, st2.st_dev); 63 failure("%s/linkfile and %s/file should be hardlinked", 64 target, target); 65 assertEqualInt(st.st_ino, st2.st_ino); 66 } 67 68 /* Symlink */ 69 r = lstat("symlink", &st); 70 failure("Failed to stat file %s/symlink, errno=%d", target, errno); 71 assertEqualInt(r, 0); 72 if (r == 0) { 73 failure("symlink should be a symlink; actual mode is %o", 74 st.st_mode); 75 assert(S_ISLNK(st.st_mode)); 76 if (S_ISLNK(st.st_mode)) { 77 r = readlink("symlink", buff, sizeof(buff)); 78 assertEqualInt(r, 4); 79 buff[r] = '\0'; 80 assertEqualString(buff, "file"); 81 } 82 } 83 84 /* dir */ 85 r = lstat("dir", &st); 86 if (r == 0) { 87 assertEqualInt(r, 0); 88 assert(S_ISDIR(st.st_mode)); 89 assertEqualInt(0775, st.st_mode & 0777); 90 } 91 } 92 93 static void 94 basic_cpio(const char *target, 95 const char *pack_options, 96 const char *unpack_options, 97 const char *se) 98 { 99 int r; 100 101 if (!assertEqualInt(0, mkdir(target, 0775))) 102 return; 103 104 /* Use the cpio program to create an archive. */ 105 r = systemf("%s -o %s < filelist >%s/archive 2>%s/pack.err", 106 testprog, pack_options, target, target); 107 failure("Error invoking %s -o %s", testprog, pack_options); 108 assertEqualInt(r, 0); 109 110 chdir(target); 111 112 /* Verify stderr. */ 113 failure("Expected: %s, options=%s", se, pack_options); 114 assertFileContents(se, strlen(se), "pack.err"); 115 116 /* 117 * Use cpio to unpack the archive into another directory. 118 */ 119 r = systemf("%s -i %s< archive >unpack.out 2>unpack.err", 120 testprog, unpack_options); 121 failure("Error invoking %s -i %s", testprog, unpack_options); 122 assertEqualInt(r, 0); 123 124 /* Verify stderr. */ 125 failure("Error invoking %s -i %s in dir %s", testprog, unpack_options, target); 126 assertFileContents(se, strlen(se), "unpack.err"); 127 128 verify_files(target); 129 130 chdir(".."); 131 } 132 133 static void 134 passthrough(const char *target) 135 { 136 int r; 137 138 if (!assertEqualInt(0, mkdir(target, 0775))) 139 return; 140 141 /* 142 * Use cpio passthrough mode to copy files to another directory. 143 */ 144 r = systemf("%s -p -W quiet %s <filelist >%s/stdout 2>%s/stderr", 145 testprog, target, target, target); 146 failure("Error invoking %s -p", testprog); 147 assertEqualInt(r, 0); 148 149 chdir(target); 150 151 /* Verify stderr. */ 152 failure("Error invoking %s -p in dir %s", 153 testprog, target); 154 assertEmptyFile("stderr"); 155 156 verify_files(target); 157 chdir(".."); 158 } 159 160 DEFINE_TEST(test_basic) 161 { 162 int fd; 163 int filelist; 164 int oldumask; 165 166 oldumask = umask(0); 167 168 /* 169 * Create an assortment of files on disk. 170 */ 171 filelist = open("filelist", O_CREAT | O_WRONLY, 0644); 172 173 /* File with 10 bytes content. */ 174 fd = open("file", O_CREAT | O_WRONLY, 0644); 175 assert(fd >= 0); 176 assertEqualInt(10, write(fd, "123456789", 10)); 177 close(fd); 178 write(filelist, "file\n", 5); 179 180 /* hardlink to above file. */ 181 assertEqualInt(0, link("file", "linkfile")); 182 write(filelist, "linkfile\n", 9); 183 184 /* Symlink to above file. */ 185 assertEqualInt(0, symlink("file", "symlink")); 186 write(filelist, "symlink\n", 8); 187 188 /* Directory. */ 189 assertEqualInt(0, mkdir("dir", 0775)); 190 write(filelist, "dir\n", 4); 191 /* All done. */ 192 close(filelist); 193 194 /* Archive/dearchive with a variety of options. */ 195 basic_cpio("copy", "", "", "1 block\n"); 196 basic_cpio("copy_odc", "--format=odc", "", "1 block\n"); 197 basic_cpio("copy_newc", "-H newc", "", "2 blocks\n"); 198 basic_cpio("copy_cpio", "-H odc", "", "1 block\n"); 199 basic_cpio("copy_ustar", "-H ustar", "", "7 blocks\n"); 200 /* Copy in one step using -p */ 201 passthrough("passthrough"); 202 203 umask(oldumask); 204 } 205