1 /*- 2 * Copyright (c) 2009 Michihiro NAKAJIMA 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 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include "test.h" 28 29 static char buff[4096]; 30 static struct { 31 const char *path; 32 mode_t mode; 33 time_t mtime; 34 uid_t uid; 35 gid_t gid; 36 } entries[] = { 37 { "./COPYING", S_IFREG | 0644, 1231975636, 1001, 1001 }, 38 { "./Makefile", S_IFREG | 0644, 1233041050, 1001, 1001 }, 39 { "./NEWS", S_IFREG | 0644, 1231975636, 1001, 1001 }, 40 { "./PROJECTS", S_IFREG | 0644, 1231975636, 1001, 1001 }, 41 { "./README", S_IFREG | 0644, 1231975636, 1001, 1001 }, 42 { "./subdir", S_IFDIR | 0755, 1233504586, 1001, 1001 }, 43 { "./subdir/README", S_IFREG | 0664, 1231975636, 1002, 1001 }, 44 { "./subdir/config", S_IFREG | 0664, 1232266273, 1003, 1003 }, 45 { "./subdir2", S_IFDIR | 0755, 1233504586, 1001, 1001 }, 46 { "./subdir3", S_IFDIR | 0755, 1233504586, 1001, 1001 }, 47 { "./subdir3/mtree", S_IFREG | 0664, 1232266273, 1003, 1003 }, 48 { NULL, 0, 0, 0, 0 } 49 }; 50 static struct { 51 const char *path; 52 mode_t mode; 53 time_t mtime; 54 uid_t uid; 55 gid_t gid; 56 } entries2[] = { 57 { "COPYING", S_IFREG | 0644, 1231975636, 1001, 1001 }, 58 { "Makefile", S_IFREG | 0644, 1233041050, 1001, 1001 }, 59 { "NEWS", S_IFREG | 0644, 1231975636, 1001, 1001 }, 60 { "PROJECTS", S_IFREG | 0644, 1231975636, 1001, 1001 }, 61 { "README", S_IFREG | 0644, 1231975636, 1001, 1001 }, 62 { "subdir", S_IFDIR | 0755, 1233504586, 1001, 1001 }, 63 { "subdir/README", S_IFREG | 0664, 1231975636, 1002, 1001 }, 64 { "subdir/config", S_IFREG | 0664, 1232266273, 1003, 1003 }, 65 { "subdir2", S_IFDIR | 0755, 1233504586, 1001, 1001 }, 66 { "subdir3", S_IFDIR | 0755, 1233504586, 1001, 1001 }, 67 { "subdir3/mtree", S_IFREG | 0664, 1232266273, 1003, 1003 }, 68 { NULL, 0, 0, 0, 0 } 69 }; 70 71 static void 72 test_write_format_mtree_sub(int use_set, int dironly) 73 { 74 struct archive_entry *ae; 75 struct archive* a; 76 size_t used; 77 int i; 78 79 /* Create a mtree format archive. */ 80 assert((a = archive_write_new()) != NULL); 81 assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); 82 if (use_set) 83 assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_option(a, NULL, "use-set", "1")); 84 if (dironly) 85 assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_option(a, NULL, "dironly", "1")); 86 assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff)-1, &used)); 87 88 /* Write entries */ 89 for (i = 0; entries[i].path != NULL; i++) { 90 assert((ae = archive_entry_new()) != NULL); 91 archive_entry_set_mtime(ae, entries[i].mtime, 0); 92 assert(entries[i].mtime == archive_entry_mtime(ae)); 93 archive_entry_set_mode(ae, entries[i].mode); 94 assert(entries[i].mode == archive_entry_mode(ae)); 95 archive_entry_set_uid(ae, entries[i].uid); 96 assert(entries[i].uid == archive_entry_uid(ae)); 97 archive_entry_set_gid(ae, entries[i].gid); 98 assert(entries[i].gid == archive_entry_gid(ae)); 99 archive_entry_copy_pathname(ae, entries[i].path); 100 if ((entries[i].mode & AE_IFMT) != S_IFDIR) 101 archive_entry_set_size(ae, 8); 102 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 103 if ((entries[i].mode & AE_IFMT) != S_IFDIR) 104 assertEqualIntA(a, 8, 105 archive_write_data(a, "Hello012", 15)); 106 archive_entry_free(ae); 107 } 108 assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); 109 assertEqualInt(ARCHIVE_OK, archive_write_free(a)); 110 111 if (use_set) { 112 const char *p; 113 114 buff[used] = '\0'; 115 assert(NULL != (p = strstr(buff, "\n/set "))); 116 if (p != NULL) { 117 char *r; 118 const char *o; 119 p++; 120 r = strchr(p, '\n'); 121 if (r != NULL) 122 *r = '\0'; 123 if (dironly) 124 o = "/set type=dir uid=1001 gid=1001 mode=755"; 125 else 126 o = "/set type=file uid=1001 gid=1001 mode=644"; 127 assertEqualString(o, p); 128 if (r != NULL) 129 *r = '\n'; 130 } 131 } 132 133 /* 134 * Read the data and check it. 135 */ 136 assert((a = archive_read_new()) != NULL); 137 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 138 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 139 assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); 140 141 /* Read entries */ 142 for (i = 0; entries[i].path != NULL; i++) { 143 if (dironly && (entries[i].mode & AE_IFMT) != S_IFDIR) 144 continue; 145 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 146 assertEqualInt(entries[i].mtime, archive_entry_mtime(ae)); 147 assertEqualInt(entries[i].mode, archive_entry_mode(ae)); 148 assertEqualInt(entries[i].uid, archive_entry_uid(ae)); 149 assertEqualInt(entries[i].gid, archive_entry_gid(ae)); 150 assertEqualString(entries[i].path, archive_entry_pathname(ae)); 151 if ((entries[i].mode & AE_IFMT) != S_IFDIR) 152 assertEqualInt(8, archive_entry_size(ae)); 153 } 154 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 155 assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 156 } 157 158 static void 159 test_write_format_mtree_sub2(int use_set, int dironly) 160 { 161 struct archive_entry *ae; 162 struct archive* a; 163 size_t used; 164 int i; 165 char str[32]; 166 167 /* Create a mtree format archive. */ 168 assert((a = archive_write_new()) != NULL); 169 assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a)); 170 if (use_set) 171 assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_option(a, NULL, "use-set", "1")); 172 if (dironly) 173 assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_option(a, NULL, "dironly", "1")); 174 assertEqualIntA(a, ARCHIVE_OK, archive_write_open_memory(a, buff, sizeof(buff)-1, &used)); 175 176 /* Write entries2 */ 177 for (i = 0; entries2[i].path != NULL; i++) { 178 assert((ae = archive_entry_new()) != NULL); 179 archive_entry_set_mtime(ae, entries2[i].mtime, 0); 180 assert(entries2[i].mtime == archive_entry_mtime(ae)); 181 archive_entry_set_mode(ae, entries2[i].mode); 182 assert(entries2[i].mode == archive_entry_mode(ae)); 183 archive_entry_set_uid(ae, entries2[i].uid); 184 assert(entries2[i].uid == archive_entry_uid(ae)); 185 archive_entry_set_gid(ae, entries2[i].gid); 186 assert(entries2[i].gid == archive_entry_gid(ae)); 187 archive_entry_copy_pathname(ae, entries2[i].path); 188 if ((entries2[i].mode & AE_IFMT) != S_IFDIR) 189 archive_entry_set_size(ae, 8); 190 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); 191 if ((entries2[i].mode & AE_IFMT) != S_IFDIR) 192 assertEqualIntA(a, 8, 193 archive_write_data(a, "Hello012", 15)); 194 archive_entry_free(ae); 195 } 196 assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a)); 197 assertEqualInt(ARCHIVE_OK, archive_write_free(a)); 198 199 if (use_set) { 200 const char *p; 201 202 buff[used] = '\0'; 203 assert(NULL != (p = strstr(buff, "\n/set "))); 204 if (p != NULL) { 205 char *r; 206 const char *o; 207 p++; 208 r = strchr(p, '\n'); 209 if (r != NULL) 210 *r = '\0'; 211 if (dironly) 212 o = "/set type=dir uid=1001 gid=1001 mode=755"; 213 else 214 o = "/set type=file uid=1001 gid=1001 mode=644"; 215 assertEqualString(o, p); 216 if (r != NULL) 217 *r = '\n'; 218 } 219 } 220 221 /* 222 * Read the data and check it. 223 */ 224 assert((a = archive_read_new()) != NULL); 225 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 226 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 227 assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, buff, used)); 228 229 /* Read entries2 */ 230 memset(str, 0, sizeof(str)); 231 strcpy(str, "./"); 232 for (i = 0; entries2[i].path != NULL; i++) { 233 if (dironly && (entries2[i].mode & AE_IFMT) != S_IFDIR) 234 continue; 235 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 236 assertEqualInt(entries2[i].mtime, archive_entry_mtime(ae)); 237 assertEqualInt(entries2[i].mode, archive_entry_mode(ae)); 238 assertEqualInt(entries2[i].uid, archive_entry_uid(ae)); 239 assertEqualInt(entries2[i].gid, archive_entry_gid(ae)); 240 strcpy(str + 2, entries2[i].path); 241 assertEqualString(str, archive_entry_pathname(ae)); 242 if ((entries2[i].mode & AE_IFMT) != S_IFDIR) 243 assertEqualInt(8, archive_entry_size(ae)); 244 } 245 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 246 assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 247 } 248 249 DEFINE_TEST(test_write_format_mtree) 250 { 251 /* Default setting */ 252 test_write_format_mtree_sub(0, 0); 253 /* Directory only */ 254 test_write_format_mtree_sub(0, 1); 255 /* Use /set keyword */ 256 test_write_format_mtree_sub(1, 0); 257 /* Use /set keyword with directory only */ 258 test_write_format_mtree_sub(1, 1); 259 } 260 261 DEFINE_TEST(test_write_format_mtree_no_leading_dotslash) 262 { 263 /* Default setting */ 264 test_write_format_mtree_sub2(0, 0); 265 /* Directory only */ 266 test_write_format_mtree_sub2(0, 1); 267 /* Use /set keyword */ 268 test_write_format_mtree_sub2(1, 0); 269 /* Use /set keyword with directory only */ 270 test_write_format_mtree_sub2(1, 1); 271 } 272