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" 26229592Smm__FBSDID("$FreeBSD$"); 27228753Smm 28228753Smm/* 29228753Smm * tar -x -P should follow existing symlinks for dirs, but not other 30228753Smm * content. Plain tar -x should remove symlinks when they're in the 31228753Smm * way of a dir extraction. 32228753Smm */ 33228753Smm 34228753Smmstatic int 35228753Smmmkfile(const char *name, int mode, const char *contents, size_t size) 36228753Smm{ 37228753Smm FILE *f = fopen(name, "wb"); 38228753Smm size_t written; 39228753Smm 40228753Smm (void)mode; /* UNUSED */ 41228753Smm if (f == NULL) 42228753Smm return (-1); 43228753Smm written = fwrite(contents, 1, size, f); 44228753Smm fclose(f); 45228753Smm if (size != written) 46228753Smm return (-1); 47228753Smm return (0); 48228753Smm} 49228753Smm 50228753SmmDEFINE_TEST(test_symlink_dir) 51228753Smm{ 52228753Smm assertUmask(0); 53228753Smm 54228753Smm assertMakeDir("source", 0755); 55228753Smm assertEqualInt(0, mkfile("source/file", 0755, "a", 1)); 56228753Smm assertEqualInt(0, mkfile("source/file2", 0755, "ab", 2)); 57228753Smm assertMakeDir("source/dir", 0755); 58228753Smm assertMakeDir("source/dir/d", 0755); 59228753Smm assertEqualInt(0, mkfile("source/dir/f", 0755, "abc", 3)); 60228753Smm assertMakeDir("source/dir2", 0755); 61228753Smm assertMakeDir("source/dir2/d2", 0755); 62228753Smm assertEqualInt(0, mkfile("source/dir2/f2", 0755, "abcd", 4)); 63228753Smm assertMakeDir("source/dir3", 0755); 64228753Smm assertMakeDir("source/dir3/d3", 0755); 65228753Smm assertEqualInt(0, mkfile("source/dir3/f3", 0755, "abcde", 5)); 66228753Smm 67228753Smm assertEqualInt(0, 68228753Smm systemf("%s -cf test.tar -C source dir dir2 dir3 file file2", 69228753Smm testprog)); 70228753Smm 71228753Smm /* 72228753Smm * Extract with -x and without -P. 73228753Smm */ 74228753Smm assertMakeDir("dest1", 0755); 75228753Smm /* "dir" is a symlink to an existing "dest1/real_dir" */ 76228753Smm assertMakeDir("dest1/real_dir", 0755); 77228753Smm if (canSymlink()) { 78228753Smm assertMakeSymlink("dest1/dir", "real_dir"); 79228753Smm /* "dir2" is a symlink to a non-existing "real_dir2" */ 80228753Smm assertMakeSymlink("dest1/dir2", "real_dir2"); 81228753Smm } else { 82228753Smm skipping("some symlink checks"); 83228753Smm } 84228753Smm /* "dir3" is a symlink to an existing "non_dir3" */ 85228753Smm assertEqualInt(0, mkfile("dest1/non_dir3", 0755, "abcdef", 6)); 86228753Smm if (canSymlink()) 87228753Smm assertMakeSymlink("dest1/dir3", "non_dir3"); 88228753Smm /* "file" is a symlink to existing "real_file" */ 89228753Smm assertEqualInt(0, mkfile("dest1/real_file", 0755, "abcdefg", 7)); 90228753Smm if (canSymlink()) { 91228753Smm assertMakeSymlink("dest1/file", "real_file"); 92228753Smm /* "file2" is a symlink to non-existing "real_file2" */ 93228753Smm assertMakeSymlink("dest1/file2", "real_file2"); 94228753Smm } 95228753Smm assertEqualInt(0, systemf("%s -xf test.tar -C dest1", testprog)); 96228753Smm 97228753Smm /* dest1/dir symlink should be replaced */ 98228753Smm failure("symlink to dir was followed when it shouldn't be"); 99228753Smm assertIsDir("dest1/dir", -1); 100228753Smm /* dest1/dir2 symlink should be replaced */ 101228753Smm failure("Broken symlink wasn't replaced with dir"); 102228753Smm assertIsDir("dest1/dir2", -1); 103228753Smm /* dest1/dir3 symlink should be replaced */ 104228753Smm failure("Symlink to non-dir wasn't replaced with dir"); 105228753Smm assertIsDir("dest1/dir3", -1); 106228753Smm /* dest1/file symlink should be replaced */ 107228753Smm failure("Symlink to existing file should be replaced"); 108228753Smm assertIsReg("dest1/file", -1); 109228753Smm /* dest1/file2 symlink should be replaced */ 110228753Smm failure("Symlink to non-existing file should be replaced"); 111228753Smm assertIsReg("dest1/file2", -1); 112228753Smm 113228753Smm /* 114228753Smm * Extract with both -x and -P 115228753Smm */ 116228753Smm assertMakeDir("dest2", 0755); 117228753Smm /* "dir" is a symlink to existing "real_dir" */ 118228753Smm assertMakeDir("dest2/real_dir", 0755); 119228753Smm if (canSymlink()) 120228753Smm assertMakeSymlink("dest2/dir", "real_dir"); 121228753Smm /* "dir2" is a symlink to a non-existing "real_dir2" */ 122228753Smm if (canSymlink()) 123228753Smm assertMakeSymlink("dest2/dir2", "real_dir2"); 124228753Smm /* "dir3" is a symlink to an existing "non_dir3" */ 125228753Smm assertEqualInt(0, mkfile("dest2/non_dir3", 0755, "abcdefgh", 8)); 126228753Smm if (canSymlink()) 127228753Smm assertMakeSymlink("dest2/dir3", "non_dir3"); 128228753Smm /* "file" is a symlink to existing "real_file" */ 129228753Smm assertEqualInt(0, mkfile("dest2/real_file", 0755, "abcdefghi", 9)); 130228753Smm if (canSymlink()) 131228753Smm assertMakeSymlink("dest2/file", "real_file"); 132228753Smm /* "file2" is a symlink to non-existing "real_file2" */ 133228753Smm if (canSymlink()) 134228753Smm assertMakeSymlink("dest2/file2", "real_file2"); 135228753Smm assertEqualInt(0, systemf("%s -xPf test.tar -C dest2", testprog)); 136228753Smm 137228753Smm /* dest2/dir symlink should be followed */ 138228753Smm if (canSymlink()) { 139228753Smm assertIsSymlink("dest2/dir", "real_dir"); 140228753Smm assertIsDir("dest2/real_dir", -1); 141228753Smm } 142228753Smm 143228753Smm /* Contents of 'dir' should be restored */ 144228753Smm assertIsDir("dest2/dir/d", -1); 145228753Smm assertIsReg("dest2/dir/f", -1); 146228753Smm assertFileSize("dest2/dir/f", 3); 147228753Smm /* dest2/dir2 symlink should be removed */ 148228753Smm failure("Broken symlink wasn't replaced with dir"); 149228753Smm assertIsDir("dest2/dir2", -1); 150228753Smm /* dest2/dir3 symlink should be removed */ 151228753Smm failure("Symlink to non-dir wasn't replaced with dir"); 152228753Smm assertIsDir("dest2/dir3", -1); 153228753Smm /* dest2/file symlink should be removed; 154228753Smm * even -P shouldn't follow symlinks for files */ 155228753Smm failure("Symlink to existing file should be removed"); 156228753Smm assertIsReg("dest2/file", -1); 157228753Smm /* dest2/file2 symlink should be removed */ 158228753Smm failure("Symlink to non-existing file should be removed"); 159228753Smm assertIsReg("dest2/file2", -1); 160228753Smm} 161