1*caf54c4fSMartin Matuska /*- 2*caf54c4fSMartin Matuska * Copyright (c) 2003-2007 Tim Kientzle 3*caf54c4fSMartin Matuska * All rights reserved. 4*caf54c4fSMartin Matuska * 5*caf54c4fSMartin Matuska * Redistribution and use in source and binary forms, with or without 6*caf54c4fSMartin Matuska * modification, are permitted provided that the following conditions 7*caf54c4fSMartin Matuska * are met: 8*caf54c4fSMartin Matuska * 1. Redistributions of source code must retain the above copyright 9*caf54c4fSMartin Matuska * notice, this list of conditions and the following disclaimer. 10*caf54c4fSMartin Matuska * 2. Redistributions in binary form must reproduce the above copyright 11*caf54c4fSMartin Matuska * notice, this list of conditions and the following disclaimer in the 12*caf54c4fSMartin Matuska * documentation and/or other materials provided with the distribution. 13*caf54c4fSMartin Matuska * 14*caf54c4fSMartin Matuska * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15*caf54c4fSMartin Matuska * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16*caf54c4fSMartin Matuska * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17*caf54c4fSMartin Matuska * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18*caf54c4fSMartin Matuska * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19*caf54c4fSMartin Matuska * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20*caf54c4fSMartin Matuska * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21*caf54c4fSMartin Matuska * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22*caf54c4fSMartin Matuska * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23*caf54c4fSMartin Matuska * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24*caf54c4fSMartin Matuska */ 25*caf54c4fSMartin Matuska #include "test.h" 26*caf54c4fSMartin Matuska __FBSDID("$FreeBSD$"); 27*caf54c4fSMartin Matuska 28*caf54c4fSMartin Matuska static int 29*caf54c4fSMartin Matuska is_octal(const char *p, size_t l) 30*caf54c4fSMartin Matuska { 31*caf54c4fSMartin Matuska while (l > 0) { 32*caf54c4fSMartin Matuska if (*p < '0' || *p > '7') 33*caf54c4fSMartin Matuska return (0); 34*caf54c4fSMartin Matuska --l; 35*caf54c4fSMartin Matuska ++p; 36*caf54c4fSMartin Matuska } 37*caf54c4fSMartin Matuska return (1); 38*caf54c4fSMartin Matuska } 39*caf54c4fSMartin Matuska 40*caf54c4fSMartin Matuska static int 41*caf54c4fSMartin Matuska from_octal(const char *p, size_t l) 42*caf54c4fSMartin Matuska { 43*caf54c4fSMartin Matuska int r = 0; 44*caf54c4fSMartin Matuska 45*caf54c4fSMartin Matuska while (l > 0) { 46*caf54c4fSMartin Matuska r *= 8; 47*caf54c4fSMartin Matuska r += *p - '0'; 48*caf54c4fSMartin Matuska --l; 49*caf54c4fSMartin Matuska ++p; 50*caf54c4fSMartin Matuska } 51*caf54c4fSMartin Matuska return (r); 52*caf54c4fSMartin Matuska } 53*caf54c4fSMartin Matuska 54*caf54c4fSMartin Matuska DEFINE_TEST(test_option_c) 55*caf54c4fSMartin Matuska { 56*caf54c4fSMartin Matuska FILE *filelist; 57*caf54c4fSMartin Matuska int r; 58*caf54c4fSMartin Matuska int uid = -1; 59*caf54c4fSMartin Matuska int dev, ino, gid; 60*caf54c4fSMartin Matuska time_t t, now; 61*caf54c4fSMartin Matuska char *p, *e; 62*caf54c4fSMartin Matuska size_t s; 63*caf54c4fSMartin Matuska 64*caf54c4fSMartin Matuska assertUmask(0); 65*caf54c4fSMartin Matuska 66*caf54c4fSMartin Matuska #if !defined(_WIN32) 67*caf54c4fSMartin Matuska uid = getuid(); 68*caf54c4fSMartin Matuska #endif 69*caf54c4fSMartin Matuska 70*caf54c4fSMartin Matuska /* 71*caf54c4fSMartin Matuska * Create an assortment of files. 72*caf54c4fSMartin Matuska * TODO: Extend this to cover more filetypes. 73*caf54c4fSMartin Matuska */ 74*caf54c4fSMartin Matuska filelist = fopen("filelist", "w"); 75*caf54c4fSMartin Matuska 76*caf54c4fSMartin Matuska /* "file" */ 77*caf54c4fSMartin Matuska assertMakeFile("file", 0644, "1234567890"); 78*caf54c4fSMartin Matuska fprintf(filelist, "file\n"); 79*caf54c4fSMartin Matuska 80*caf54c4fSMartin Matuska /* "symlink" */ 81*caf54c4fSMartin Matuska if (canSymlink()) { 82*caf54c4fSMartin Matuska assertMakeSymlink("symlink", "file"); 83*caf54c4fSMartin Matuska fprintf(filelist, "symlink\n"); 84*caf54c4fSMartin Matuska } 85*caf54c4fSMartin Matuska 86*caf54c4fSMartin Matuska /* "dir" */ 87*caf54c4fSMartin Matuska assertMakeDir("dir", 0775); 88*caf54c4fSMartin Matuska /* Record some facts about what we just created: */ 89*caf54c4fSMartin Matuska now = time(NULL); /* They were all created w/in last two seconds. */ 90*caf54c4fSMartin Matuska fprintf(filelist, "dir\n"); 91*caf54c4fSMartin Matuska 92*caf54c4fSMartin Matuska /* Use the cpio program to create an archive. */ 93*caf54c4fSMartin Matuska fclose(filelist); 94*caf54c4fSMartin Matuska r = systemf("%s -oc <filelist >basic.out 2>basic.err", testprog); 95*caf54c4fSMartin Matuska /* Verify that nothing went to stderr. */ 96*caf54c4fSMartin Matuska assertTextFileContents("1 block\n", "basic.err"); 97*caf54c4fSMartin Matuska 98*caf54c4fSMartin Matuska /* Assert that the program finished. */ 99*caf54c4fSMartin Matuska failure("%s -oc crashed", testprog); 100*caf54c4fSMartin Matuska if (!assertEqualInt(r, 0)) 101*caf54c4fSMartin Matuska return; 102*caf54c4fSMartin Matuska 103*caf54c4fSMartin Matuska /* Verify that stdout is a well-formed cpio file in "odc" format. */ 104*caf54c4fSMartin Matuska p = slurpfile(&s, "basic.out"); 105*caf54c4fSMartin Matuska assertEqualInt(s, 512); 106*caf54c4fSMartin Matuska e = p; 107*caf54c4fSMartin Matuska 108*caf54c4fSMartin Matuska /* 109*caf54c4fSMartin Matuska * Some of these assertions could be stronger, but it's 110*caf54c4fSMartin Matuska * a little tricky because they depend on the local environment. 111*caf54c4fSMartin Matuska */ 112*caf54c4fSMartin Matuska 113*caf54c4fSMartin Matuska /* First entry is "file" */ 114*caf54c4fSMartin Matuska assert(is_octal(e, 76)); /* Entire header is octal digits. */ 115*caf54c4fSMartin Matuska assertEqualMem(e + 0, "070707", 6); /* Magic */ 116*caf54c4fSMartin Matuska assert(is_octal(e + 6, 6)); /* dev */ 117*caf54c4fSMartin Matuska dev = from_octal(e + 6, 6); 118*caf54c4fSMartin Matuska assert(is_octal(e + 12, 6)); /* ino */ 119*caf54c4fSMartin Matuska ino = from_octal(e + 12, 6); 120*caf54c4fSMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__) 121*caf54c4fSMartin Matuska /* Group members bits and others bits do not work. */ 122*caf54c4fSMartin Matuska assertEqualMem(e + 18, "100666", 6); /* Mode */ 123*caf54c4fSMartin Matuska #else 124*caf54c4fSMartin Matuska assertEqualMem(e + 18, "100644", 6); /* Mode */ 125*caf54c4fSMartin Matuska #endif 126*caf54c4fSMartin Matuska if (uid < 0) 127*caf54c4fSMartin Matuska uid = from_octal(e + 24, 6); 128*caf54c4fSMartin Matuska assertEqualInt(from_octal(e + 24, 6), uid); /* uid */ 129*caf54c4fSMartin Matuska assert(is_octal(e + 30, 6)); /* gid */ 130*caf54c4fSMartin Matuska gid = from_octal(e + 30, 6); 131*caf54c4fSMartin Matuska assertEqualMem(e + 36, "000001", 6); /* nlink */ 132*caf54c4fSMartin Matuska failure("file entries should not have rdev set (dev field was 0%o)", 133*caf54c4fSMartin Matuska dev); 134*caf54c4fSMartin Matuska assertEqualMem(e + 42, "000000", 6); /* rdev */ 135*caf54c4fSMartin Matuska t = from_octal(e + 48, 11); /* mtime */ 136*caf54c4fSMartin Matuska assert(t <= now); /* File wasn't created in future. */ 137*caf54c4fSMartin Matuska assert(t >= now - 2); /* File was created w/in last 2 secs. */ 138*caf54c4fSMartin Matuska assertEqualMem(e + 59, "000005", 6); /* Name size */ 139*caf54c4fSMartin Matuska assertEqualMem(e + 65, "00000000012", 11); /* File size */ 140*caf54c4fSMartin Matuska assertEqualMem(e + 76, "file\0", 5); /* Name contents */ 141*caf54c4fSMartin Matuska assertEqualMem(e + 81, "1234567890", 10); /* File contents */ 142*caf54c4fSMartin Matuska e += 91; 143*caf54c4fSMartin Matuska 144*caf54c4fSMartin Matuska /* "symlink" pointing to "file" */ 145*caf54c4fSMartin Matuska if (canSymlink()) { 146*caf54c4fSMartin Matuska assert(is_octal(e, 76)); /* Entire header is octal digits. */ 147*caf54c4fSMartin Matuska assertEqualMem(e + 0, "070707", 6); /* Magic */ 148*caf54c4fSMartin Matuska assertEqualInt(dev, from_octal(e + 6, 6)); /* dev */ 149*caf54c4fSMartin Matuska assert(ino != from_octal(e + 12, 6)); /* ino */ 150*caf54c4fSMartin Matuska #if !defined(_WIN32) || defined(__CYGWIN__) 151*caf54c4fSMartin Matuska /* On Windows, symbolic link and group members bits and 152*caf54c4fSMartin Matuska * others bits do not work. */ 153*caf54c4fSMartin Matuska assertEqualMem(e + 18, "120777", 6); /* Mode */ 154*caf54c4fSMartin Matuska #endif 155*caf54c4fSMartin Matuska assertEqualInt(from_octal(e + 24, 6), uid); /* uid */ 156*caf54c4fSMartin Matuska assertEqualInt(gid, from_octal(e + 30, 6)); /* gid */ 157*caf54c4fSMartin Matuska assertEqualMem(e + 36, "000001", 6); /* nlink */ 158*caf54c4fSMartin Matuska failure("file entries should have rdev == 0 (dev was 0%o)", 159*caf54c4fSMartin Matuska from_octal(e + 6, 6)); 160*caf54c4fSMartin Matuska assertEqualMem(e + 42, "000000", 6); /* rdev */ 161*caf54c4fSMartin Matuska t = from_octal(e + 48, 11); /* mtime */ 162*caf54c4fSMartin Matuska assert(t <= now); /* File wasn't created in future. */ 163*caf54c4fSMartin Matuska assert(t >= now - 2); /* File was created w/in last 2 secs. */ 164*caf54c4fSMartin Matuska assertEqualMem(e + 59, "000010", 6); /* Name size */ 165*caf54c4fSMartin Matuska assertEqualMem(e + 65, "00000000004", 11); /* File size */ 166*caf54c4fSMartin Matuska assertEqualMem(e + 76, "symlink\0", 8); /* Name contents */ 167*caf54c4fSMartin Matuska assertEqualMem(e + 84, "file", 4); /* Symlink target. */ 168*caf54c4fSMartin Matuska e += 88; 169*caf54c4fSMartin Matuska } 170*caf54c4fSMartin Matuska 171*caf54c4fSMartin Matuska /* "dir" */ 172*caf54c4fSMartin Matuska assert(is_octal(e, 76)); 173*caf54c4fSMartin Matuska assertEqualMem(e + 0, "070707", 6); /* Magic */ 174*caf54c4fSMartin Matuska /* Dev should be same as first entry. */ 175*caf54c4fSMartin Matuska assert(is_octal(e + 6, 6)); /* dev */ 176*caf54c4fSMartin Matuska assertEqualInt(dev, from_octal(e + 6, 6)); 177*caf54c4fSMartin Matuska /* Ino must be different from first entry. */ 178*caf54c4fSMartin Matuska assert(is_octal(e + 12, 6)); /* ino */ 179*caf54c4fSMartin Matuska assert(ino != from_octal(e + 12, 6)); 180*caf54c4fSMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__) 181*caf54c4fSMartin Matuska /* Group members bits and others bits do not work. */ 182*caf54c4fSMartin Matuska assertEqualMem(e + 18, "040777", 6); /* Mode */ 183*caf54c4fSMartin Matuska #else 184*caf54c4fSMartin Matuska /* Accept 042775 to accomodate systems where sgid bit propagates. */ 185*caf54c4fSMartin Matuska if (memcmp(e + 18, "042775", 6) != 0) 186*caf54c4fSMartin Matuska assertEqualMem(e + 18, "040775", 6); /* Mode */ 187*caf54c4fSMartin Matuska #endif 188*caf54c4fSMartin Matuska assertEqualInt(from_octal(e + 24, 6), uid); /* uid */ 189*caf54c4fSMartin Matuska /* Gid should be same as first entry. */ 190*caf54c4fSMartin Matuska assert(is_octal(e + 30, 6)); /* gid */ 191*caf54c4fSMartin Matuska assertEqualInt(gid, from_octal(e + 30, 6)); 192*caf54c4fSMartin Matuska #ifndef NLINKS_INACCURATE_FOR_DIRS 193*caf54c4fSMartin Matuska assertEqualMem(e + 36, "000002", 6); /* Nlink */ 194*caf54c4fSMartin Matuska #endif 195*caf54c4fSMartin Matuska t = from_octal(e + 48, 11); /* mtime */ 196*caf54c4fSMartin Matuska assert(t <= now); /* File wasn't created in future. */ 197*caf54c4fSMartin Matuska assert(t >= now - 2); /* File was created w/in last 2 secs. */ 198*caf54c4fSMartin Matuska assertEqualMem(e + 59, "000004", 6); /* Name size */ 199*caf54c4fSMartin Matuska assertEqualMem(e + 65, "00000000000", 11); /* File size */ 200*caf54c4fSMartin Matuska assertEqualMem(e + 76, "dir\0", 4); /* name */ 201*caf54c4fSMartin Matuska e += 80; 202*caf54c4fSMartin Matuska 203*caf54c4fSMartin Matuska /* TODO: Verify other types of entries. */ 204*caf54c4fSMartin Matuska 205*caf54c4fSMartin Matuska /* Last entry is end-of-archive marker. */ 206*caf54c4fSMartin Matuska assert(is_octal(e, 76)); 207*caf54c4fSMartin Matuska assertEqualMem(e + 0, "070707", 6); /* Magic */ 208*caf54c4fSMartin Matuska assertEqualMem(e + 6, "000000", 6); /* dev */ 209*caf54c4fSMartin Matuska assertEqualMem(e + 12, "000000", 6); /* ino */ 210*caf54c4fSMartin Matuska assertEqualMem(e + 18, "000000", 6); /* Mode */ 211*caf54c4fSMartin Matuska assertEqualMem(e + 24, "000000", 6); /* uid */ 212*caf54c4fSMartin Matuska assertEqualMem(e + 30, "000000", 6); /* gid */ 213*caf54c4fSMartin Matuska assertEqualMem(e + 36, "000001", 6); /* Nlink */ 214*caf54c4fSMartin Matuska assertEqualMem(e + 42, "000000", 6); /* rdev */ 215*caf54c4fSMartin Matuska assertEqualMem(e + 48, "00000000000", 11); /* mtime */ 216*caf54c4fSMartin Matuska assertEqualMem(e + 59, "000013", 6); /* Name size */ 217*caf54c4fSMartin Matuska assertEqualMem(e + 65, "00000000000", 11); /* File size */ 218*caf54c4fSMartin Matuska assertEqualMem(e + 76, "TRAILER!!!\0", 11); /* Name */ 219*caf54c4fSMartin Matuska 220*caf54c4fSMartin Matuska free(p); 221*caf54c4fSMartin Matuska } 222