1caf54c4fSMartin Matuska /*- 2*bd66c1b4SMartin Matuska * SPDX-License-Identifier: BSD-2-Clause 3*bd66c1b4SMartin Matuska * 4caf54c4fSMartin Matuska * Copyright (c) 2003-2007 Tim Kientzle 5caf54c4fSMartin Matuska * All rights reserved. 6caf54c4fSMartin Matuska */ 7caf54c4fSMartin Matuska #include "test.h" 8caf54c4fSMartin Matuska 9caf54c4fSMartin Matuska static int 10caf54c4fSMartin Matuska is_octal(const char *p, size_t l) 11caf54c4fSMartin Matuska { 12caf54c4fSMartin Matuska while (l > 0) { 13caf54c4fSMartin Matuska if (*p < '0' || *p > '7') 14caf54c4fSMartin Matuska return (0); 15caf54c4fSMartin Matuska --l; 16caf54c4fSMartin Matuska ++p; 17caf54c4fSMartin Matuska } 18caf54c4fSMartin Matuska return (1); 19caf54c4fSMartin Matuska } 20caf54c4fSMartin Matuska 21e64fe029SMartin Matuska static long long int 22caf54c4fSMartin Matuska from_octal(const char *p, size_t l) 23caf54c4fSMartin Matuska { 24e64fe029SMartin Matuska long long int r = 0; 25caf54c4fSMartin Matuska 26caf54c4fSMartin Matuska while (l > 0) { 27caf54c4fSMartin Matuska r *= 8; 28caf54c4fSMartin Matuska r += *p - '0'; 29caf54c4fSMartin Matuska --l; 30caf54c4fSMartin Matuska ++p; 31caf54c4fSMartin Matuska } 32caf54c4fSMartin Matuska return (r); 33caf54c4fSMartin Matuska } 34caf54c4fSMartin Matuska 356c95142eSMartin Matuska #if !defined(_WIN32) || defined(__CYGWIN__) 366c95142eSMartin Matuska static int 376c95142eSMartin Matuska nlinks(const char *p) 386c95142eSMartin Matuska { 396c95142eSMartin Matuska struct stat st; 406c95142eSMartin Matuska assertEqualInt(0, stat(p, &st)); 416c95142eSMartin Matuska return st.st_nlink; 426c95142eSMartin Matuska } 436c95142eSMartin Matuska #endif 446c95142eSMartin Matuska 45caf54c4fSMartin Matuska DEFINE_TEST(test_option_c) 46caf54c4fSMartin Matuska { 47caf54c4fSMartin Matuska FILE *filelist; 48caf54c4fSMartin Matuska int r; 49cdf63a70SMartin Matuska int uid = 1000; 50cdf63a70SMartin Matuska int dev, ino, gid = 1000; 51caf54c4fSMartin Matuska time_t t, now; 52caf54c4fSMartin Matuska char *p, *e; 53caf54c4fSMartin Matuska size_t s; 54caf54c4fSMartin Matuska 55caf54c4fSMartin Matuska assertUmask(0); 56caf54c4fSMartin Matuska 57caf54c4fSMartin Matuska /* 58caf54c4fSMartin Matuska * Create an assortment of files. 59caf54c4fSMartin Matuska * TODO: Extend this to cover more filetypes. 60caf54c4fSMartin Matuska */ 61caf54c4fSMartin Matuska filelist = fopen("filelist", "w"); 62caf54c4fSMartin Matuska 63caf54c4fSMartin Matuska /* "file" */ 64caf54c4fSMartin Matuska assertMakeFile("file", 0644, "1234567890"); 65caf54c4fSMartin Matuska fprintf(filelist, "file\n"); 66caf54c4fSMartin Matuska 67caf54c4fSMartin Matuska /* "symlink" */ 68caf54c4fSMartin Matuska if (canSymlink()) { 6952c2bb75SMartin Matuska assertMakeSymlink("symlink", "file", 0); 70caf54c4fSMartin Matuska fprintf(filelist, "symlink\n"); 71caf54c4fSMartin Matuska } 72caf54c4fSMartin Matuska 73caf54c4fSMartin Matuska /* "dir" */ 74caf54c4fSMartin Matuska assertMakeDir("dir", 0775); 75caf54c4fSMartin Matuska /* Record some facts about what we just created: */ 76caf54c4fSMartin Matuska now = time(NULL); /* They were all created w/in last two seconds. */ 77caf54c4fSMartin Matuska fprintf(filelist, "dir\n"); 78caf54c4fSMartin Matuska 79caf54c4fSMartin Matuska /* Use the cpio program to create an archive. */ 80caf54c4fSMartin Matuska fclose(filelist); 81cdf63a70SMartin Matuska r = systemf("%s -R 1000:1000 -oc <filelist >basic.out 2>basic.err", testprog); 82caf54c4fSMartin Matuska /* Verify that nothing went to stderr. */ 83caf54c4fSMartin Matuska assertTextFileContents("1 block\n", "basic.err"); 84caf54c4fSMartin Matuska 85caf54c4fSMartin Matuska /* Assert that the program finished. */ 86caf54c4fSMartin Matuska failure("%s -oc crashed", testprog); 87caf54c4fSMartin Matuska if (!assertEqualInt(r, 0)) 88caf54c4fSMartin Matuska return; 89caf54c4fSMartin Matuska 90caf54c4fSMartin Matuska /* Verify that stdout is a well-formed cpio file in "odc" format. */ 91caf54c4fSMartin Matuska p = slurpfile(&s, "basic.out"); 92caf54c4fSMartin Matuska assertEqualInt(s, 512); 93caf54c4fSMartin Matuska e = p; 94caf54c4fSMartin Matuska 95caf54c4fSMartin Matuska /* 96caf54c4fSMartin Matuska * Some of these assertions could be stronger, but it's 97caf54c4fSMartin Matuska * a little tricky because they depend on the local environment. 98caf54c4fSMartin Matuska */ 99caf54c4fSMartin Matuska 100caf54c4fSMartin Matuska /* First entry is "file" */ 101caf54c4fSMartin Matuska assert(is_octal(e, 76)); /* Entire header is octal digits. */ 102caf54c4fSMartin Matuska assertEqualMem(e + 0, "070707", 6); /* Magic */ 103caf54c4fSMartin Matuska assert(is_octal(e + 6, 6)); /* dev */ 104*bd66c1b4SMartin Matuska dev = (int)from_octal(e + 6, 6); 105caf54c4fSMartin Matuska assert(is_octal(e + 12, 6)); /* ino */ 106*bd66c1b4SMartin Matuska ino = (int)from_octal(e + 12, 6); 107caf54c4fSMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__) 108caf54c4fSMartin Matuska /* Group members bits and others bits do not work. */ 109caf54c4fSMartin Matuska assertEqualMem(e + 18, "100666", 6); /* Mode */ 110caf54c4fSMartin Matuska #else 111caf54c4fSMartin Matuska assertEqualMem(e + 18, "100644", 6); /* Mode */ 112caf54c4fSMartin Matuska #endif 113caf54c4fSMartin Matuska if (uid < 0) 114*bd66c1b4SMartin Matuska uid = (int)from_octal(e + 24, 6); 115caf54c4fSMartin Matuska assertEqualInt(from_octal(e + 24, 6), uid); /* uid */ 116caf54c4fSMartin Matuska assert(is_octal(e + 30, 6)); /* gid */ 117*bd66c1b4SMartin Matuska gid = (int)from_octal(e + 30, 6); 118caf54c4fSMartin Matuska assertEqualMem(e + 36, "000001", 6); /* nlink */ 119caf54c4fSMartin Matuska failure("file entries should not have rdev set (dev field was 0%o)", 120caf54c4fSMartin Matuska dev); 121caf54c4fSMartin Matuska assertEqualMem(e + 42, "000000", 6); /* rdev */ 122caf54c4fSMartin Matuska t = from_octal(e + 48, 11); /* mtime */ 123caf54c4fSMartin Matuska assert(t <= now); /* File wasn't created in future. */ 124caf54c4fSMartin Matuska assert(t >= now - 2); /* File was created w/in last 2 secs. */ 125caf54c4fSMartin Matuska assertEqualMem(e + 59, "000005", 6); /* Name size */ 126caf54c4fSMartin Matuska assertEqualMem(e + 65, "00000000012", 11); /* File size */ 127caf54c4fSMartin Matuska assertEqualMem(e + 76, "file\0", 5); /* Name contents */ 128caf54c4fSMartin Matuska assertEqualMem(e + 81, "1234567890", 10); /* File contents */ 129caf54c4fSMartin Matuska e += 91; 130caf54c4fSMartin Matuska 131caf54c4fSMartin Matuska /* "symlink" pointing to "file" */ 132caf54c4fSMartin Matuska if (canSymlink()) { 133caf54c4fSMartin Matuska assert(is_octal(e, 76)); /* Entire header is octal digits. */ 134caf54c4fSMartin Matuska assertEqualMem(e + 0, "070707", 6); /* Magic */ 135caf54c4fSMartin Matuska assertEqualInt(dev, from_octal(e + 6, 6)); /* dev */ 136caf54c4fSMartin Matuska assert(ino != from_octal(e + 12, 6)); /* ino */ 137caf54c4fSMartin Matuska #if !defined(_WIN32) || defined(__CYGWIN__) 138caf54c4fSMartin Matuska /* On Windows, symbolic link and group members bits and 139caf54c4fSMartin Matuska * others bits do not work. */ 140caf54c4fSMartin Matuska assertEqualMem(e + 18, "120777", 6); /* Mode */ 141caf54c4fSMartin Matuska #endif 142caf54c4fSMartin Matuska assertEqualInt(from_octal(e + 24, 6), uid); /* uid */ 143caf54c4fSMartin Matuska assertEqualInt(gid, from_octal(e + 30, 6)); /* gid */ 144caf54c4fSMartin Matuska assertEqualMem(e + 36, "000001", 6); /* nlink */ 145e64fe029SMartin Matuska failure("file entries should have rdev == 0 (dev was 0%llo)", 146caf54c4fSMartin Matuska from_octal(e + 6, 6)); 147caf54c4fSMartin Matuska assertEqualMem(e + 42, "000000", 6); /* rdev */ 148caf54c4fSMartin Matuska t = from_octal(e + 48, 11); /* mtime */ 149caf54c4fSMartin Matuska assert(t <= now); /* File wasn't created in future. */ 150caf54c4fSMartin Matuska assert(t >= now - 2); /* File was created w/in last 2 secs. */ 151caf54c4fSMartin Matuska assertEqualMem(e + 59, "000010", 6); /* Name size */ 152caf54c4fSMartin Matuska assertEqualMem(e + 65, "00000000004", 11); /* File size */ 153caf54c4fSMartin Matuska assertEqualMem(e + 76, "symlink\0", 8); /* Name contents */ 154caf54c4fSMartin Matuska assertEqualMem(e + 84, "file", 4); /* Symlink target. */ 155caf54c4fSMartin Matuska e += 88; 156caf54c4fSMartin Matuska } 157caf54c4fSMartin Matuska 158caf54c4fSMartin Matuska /* "dir" */ 159caf54c4fSMartin Matuska assert(is_octal(e, 76)); 160caf54c4fSMartin Matuska assertEqualMem(e + 0, "070707", 6); /* Magic */ 161caf54c4fSMartin Matuska /* Dev should be same as first entry. */ 162caf54c4fSMartin Matuska assert(is_octal(e + 6, 6)); /* dev */ 163caf54c4fSMartin Matuska assertEqualInt(dev, from_octal(e + 6, 6)); 164caf54c4fSMartin Matuska /* Ino must be different from first entry. */ 165caf54c4fSMartin Matuska assert(is_octal(e + 12, 6)); /* ino */ 166caf54c4fSMartin Matuska assert(ino != from_octal(e + 12, 6)); 167caf54c4fSMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__) 168caf54c4fSMartin Matuska /* Group members bits and others bits do not work. */ 169caf54c4fSMartin Matuska assertEqualMem(e + 18, "040777", 6); /* Mode */ 170caf54c4fSMartin Matuska #else 1716c95142eSMartin Matuska /* Accept 042775 to accommodate systems where sgid bit propagates. */ 172caf54c4fSMartin Matuska if (memcmp(e + 18, "042775", 6) != 0) 173caf54c4fSMartin Matuska assertEqualMem(e + 18, "040775", 6); /* Mode */ 174caf54c4fSMartin Matuska #endif 1756c95142eSMartin Matuska assertEqualInt(uid, from_octal(e + 24, 6)); /* uid */ 176caf54c4fSMartin Matuska /* Gid should be same as first entry. */ 177caf54c4fSMartin Matuska assert(is_octal(e + 30, 6)); /* gid */ 178caf54c4fSMartin Matuska assertEqualInt(gid, from_octal(e + 30, 6)); 1796c95142eSMartin Matuska 1806c95142eSMartin Matuska #if !defined(_WIN32) || defined(__CYGWIN__) 1816c95142eSMartin Matuska assertEqualInt(nlinks("dir"), from_octal(e + 36, 6)); /* Nlink */ 182caf54c4fSMartin Matuska #endif 1836c95142eSMartin Matuska 184caf54c4fSMartin Matuska t = from_octal(e + 48, 11); /* mtime */ 185caf54c4fSMartin Matuska assert(t <= now); /* File wasn't created in future. */ 186caf54c4fSMartin Matuska assert(t >= now - 2); /* File was created w/in last 2 secs. */ 187caf54c4fSMartin Matuska assertEqualMem(e + 59, "000004", 6); /* Name size */ 188caf54c4fSMartin Matuska assertEqualMem(e + 65, "00000000000", 11); /* File size */ 189caf54c4fSMartin Matuska assertEqualMem(e + 76, "dir\0", 4); /* name */ 190caf54c4fSMartin Matuska e += 80; 191caf54c4fSMartin Matuska 192caf54c4fSMartin Matuska /* TODO: Verify other types of entries. */ 193caf54c4fSMartin Matuska 194caf54c4fSMartin Matuska /* Last entry is end-of-archive marker. */ 195caf54c4fSMartin Matuska assert(is_octal(e, 76)); 196caf54c4fSMartin Matuska assertEqualMem(e + 0, "070707", 6); /* Magic */ 197caf54c4fSMartin Matuska assertEqualMem(e + 6, "000000", 6); /* dev */ 198caf54c4fSMartin Matuska assertEqualMem(e + 12, "000000", 6); /* ino */ 199caf54c4fSMartin Matuska assertEqualMem(e + 18, "000000", 6); /* Mode */ 200caf54c4fSMartin Matuska assertEqualMem(e + 24, "000000", 6); /* uid */ 201caf54c4fSMartin Matuska assertEqualMem(e + 30, "000000", 6); /* gid */ 202caf54c4fSMartin Matuska assertEqualMem(e + 36, "000001", 6); /* Nlink */ 203caf54c4fSMartin Matuska assertEqualMem(e + 42, "000000", 6); /* rdev */ 204caf54c4fSMartin Matuska assertEqualMem(e + 48, "00000000000", 11); /* mtime */ 205caf54c4fSMartin Matuska assertEqualMem(e + 59, "000013", 6); /* Name size */ 206caf54c4fSMartin Matuska assertEqualMem(e + 65, "00000000000", 11); /* File size */ 207caf54c4fSMartin Matuska assertEqualMem(e + 76, "TRAILER!!!\0", 11); /* Name */ 208caf54c4fSMartin Matuska 209caf54c4fSMartin Matuska free(p); 210caf54c4fSMartin Matuska } 211