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" 26228763Smm__FBSDID("$FreeBSD$"); 27228753Smm 28228753Smm/* 29228753Smm * Exercise various lengths of filenames in ustar archives. 30228753Smm */ 31228753Smm 32228753Smmstatic void 33228753Smmtest_filename(const char *prefix, int dlen, int flen) 34228753Smm{ 35228753Smm char buff[8192]; 36228753Smm char filename[400]; 37228753Smm char dirname[400]; 38228753Smm struct archive_entry *ae; 39228753Smm struct archive *a; 40228753Smm size_t used; 41228753Smm int separator = 0; 42228753Smm int i = 0; 43228753Smm 44228753Smm if (prefix != NULL) { 45228753Smm strcpy(filename, prefix); 46228753Smm i = (int)strlen(prefix); 47228753Smm } 48228753Smm if (dlen > 0) { 49228753Smm for (; i < dlen; i++) 50228753Smm filename[i] = 'a'; 51228753Smm filename[i++] = '/'; 52228753Smm separator = 1; 53228753Smm } 54228753Smm for (; i < dlen + flen + separator; i++) 55228753Smm filename[i] = 'b'; 56228753Smm filename[i] = '\0'; 57228753Smm 58228753Smm strcpy(dirname, filename); 59228753Smm 60228753Smm /* Create a new archive in memory. */ 61228753Smm assert((a = archive_write_new()) != NULL); 62228753Smm assertA(0 == archive_write_set_format_ustar(a)); 63248616Smm assertA(0 == archive_write_add_filter_none(a)); 64228753Smm assertA(0 == archive_write_set_bytes_per_block(a,0)); 65228753Smm assertA(0 == archive_write_open_memory(a, buff, sizeof(buff), &used)); 66228753Smm 67228753Smm /* 68228753Smm * Write a file to it. 69228753Smm */ 70228753Smm assert((ae = archive_entry_new()) != NULL); 71228753Smm archive_entry_copy_pathname(ae, filename); 72228753Smm archive_entry_set_mode(ae, S_IFREG | 0755); 73228753Smm failure("dlen=%d, flen=%d", dlen, flen); 74228753Smm if (flen > 100) { 75228753Smm assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); 76228753Smm } else { 77228753Smm assertEqualIntA(a, 0, archive_write_header(a, ae)); 78228753Smm } 79228753Smm archive_entry_free(ae); 80228753Smm 81228753Smm /* 82228753Smm * Write a dir to it (without trailing '/'). 83228753Smm */ 84228753Smm assert((ae = archive_entry_new()) != NULL); 85228753Smm archive_entry_copy_pathname(ae, dirname); 86228753Smm archive_entry_set_mode(ae, S_IFDIR | 0755); 87228753Smm failure("dlen=%d, flen=%d", dlen, flen); 88228753Smm if (flen >= 100) { 89228753Smm assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); 90228753Smm } else { 91228753Smm assertEqualIntA(a, 0, archive_write_header(a, ae)); 92228753Smm } 93228753Smm archive_entry_free(ae); 94228753Smm 95228753Smm /* Tar adds a '/' to directory names. */ 96228753Smm strcat(dirname, "/"); 97228753Smm 98228753Smm /* 99228753Smm * Write a dir to it (with trailing '/'). 100228753Smm */ 101228753Smm assert((ae = archive_entry_new()) != NULL); 102228753Smm archive_entry_copy_pathname(ae, dirname); 103228753Smm archive_entry_set_mode(ae, S_IFDIR | 0755); 104228753Smm failure("dlen=%d, flen=%d", dlen, flen); 105228753Smm if (flen >= 100) { 106228753Smm assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); 107228753Smm } else { 108228753Smm assertEqualIntA(a, 0, archive_write_header(a, ae)); 109228753Smm } 110228753Smm archive_entry_free(ae); 111228753Smm 112228753Smm /* Close out the archive. */ 113232153Smm assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); 114232153Smm assertEqualInt(ARCHIVE_OK, archive_write_free(a)); 115228753Smm 116228753Smm /* 117228753Smm * Now, read the data back. 118228753Smm */ 119228753Smm assert((a = archive_read_new()) != NULL); 120228753Smm assertA(0 == archive_read_support_format_all(a)); 121232153Smm assertA(0 == archive_read_support_filter_all(a)); 122228753Smm assertA(0 == archive_read_open_memory(a, buff, used)); 123228753Smm 124228753Smm if (flen <= 100) { 125228753Smm /* Read the file and check the filename. */ 126228753Smm assertA(0 == archive_read_next_header(a, &ae)); 127228753Smm failure("dlen=%d, flen=%d", dlen, flen); 128228753Smm assertEqualString(filename, archive_entry_pathname(ae)); 129228753Smm assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae)); 130228753Smm } 131228753Smm 132228753Smm /* 133228753Smm * Read the two dirs and check the names. 134228753Smm * 135228753Smm * Both dirs should read back with the same name, since 136228753Smm * tar should add a trailing '/' to any dir that doesn't 137228753Smm * already have one. 138228753Smm */ 139228753Smm if (flen <= 99) { 140228753Smm assertA(0 == archive_read_next_header(a, &ae)); 141228753Smm assert((S_IFDIR | 0755) == archive_entry_mode(ae)); 142228753Smm failure("dlen=%d, flen=%d", dlen, flen); 143228753Smm assertEqualString(dirname, archive_entry_pathname(ae)); 144228753Smm } 145228753Smm 146228753Smm if (flen <= 99) { 147228753Smm assertA(0 == archive_read_next_header(a, &ae)); 148228753Smm assert((S_IFDIR | 0755) == archive_entry_mode(ae)); 149228753Smm assertEqualString(dirname, archive_entry_pathname(ae)); 150228753Smm } 151228753Smm 152228753Smm /* Verify the end of the archive. */ 153228753Smm failure("This fails if entries were written that should not have been written. dlen=%d, flen=%d", dlen, flen); 154228753Smm assertEqualInt(1, archive_read_next_header(a, &ae)); 155232153Smm assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 156232153Smm assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 157228753Smm} 158228753Smm 159228753SmmDEFINE_TEST(test_ustar_filenames) 160228753Smm{ 161228753Smm int dlen, flen; 162228753Smm 163228753Smm /* Try a bunch of different file/dir lengths that add up 164228753Smm * to just a little less or a little more than 100 bytes. 165228753Smm * This exercises the code that splits paths between ustar 166228753Smm * filename and prefix fields. 167228753Smm */ 168228753Smm for (dlen = 5; dlen < 70; dlen += 5) { 169228753Smm for (flen = 100 - dlen - 5; flen < 100 - dlen + 5; flen++) { 170228753Smm test_filename(NULL, dlen, flen); 171228753Smm test_filename("/", dlen, flen); 172228753Smm } 173228753Smm } 174228753Smm 175228753Smm /* Probe the 100-char limit for paths with no '/'. */ 176228753Smm for (flen = 90; flen < 110; flen++) { 177228753Smm test_filename(NULL, 0, flen); 178228753Smm test_filename("/", dlen, flen); 179228753Smm } 180228753Smm 181228753Smm /* XXXX TODO Probe the 100-char limit with a dir prefix. */ 182228753Smm /* XXXX TODO Probe the 255-char total limit. */ 183228753Smm} 184