1 /* $NetBSD: iso9660_rrip.c,v 1.14 2014/05/30 13:14:47 martin Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan 7 * Perez-Rathke and Ram Vedam. All rights reserved. 8 * 9 * This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys, 10 * Alan Perez-Rathke and Ram Vedam. 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above 18 * copyright notice, this list of conditions and the following 19 * disclaimer in the documentation and/or other materials provided 20 * with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN 23 * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 * DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN 27 * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 30 * USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 34 * OF SUCH DAMAGE. 35 */ 36 /* This will hold all the function definitions 37 * defined in iso9660_rrip.h 38 */ 39 40 #include <sys/cdefs.h> 41 #include <sys/queue.h> 42 #include <sys/types.h> 43 #include <stdio.h> 44 45 #include "makefs.h" 46 #include "cd9660.h" 47 #include "iso9660_rrip.h" 48 #include <util.h> 49 50 static void cd9660_rrip_initialize_inode(iso9660_disk *, cd9660node *); 51 static int cd9660_susp_handle_continuation(iso9660_disk *, cd9660node *); 52 static int cd9660_susp_handle_continuation_common(iso9660_disk *, cd9660node *, 53 int); 54 55 int 56 cd9660_susp_initialize(iso9660_disk *diskStructure, cd9660node *node, 57 cd9660node *parent, cd9660node *grandparent) 58 { 59 cd9660node *cn; 60 int r; 61 62 /* Make sure the node is not NULL. If it is, there are major problems */ 63 assert(node != NULL); 64 65 if (!(node->type & CD9660_TYPE_DOT) && 66 !(node->type & CD9660_TYPE_DOTDOT)) 67 TAILQ_INIT(&(node->head)); 68 if (node->dot_record != 0) 69 TAILQ_INIT(&(node->dot_record->head)); 70 if (node->dot_dot_record != 0) 71 TAILQ_INIT(&(node->dot_dot_record->head)); 72 73 if (diskStructure->rr_inode_next == 0) { 74 RB_INIT(&diskStructure->rr_inode_map); 75 diskStructure->rr_inode_next = 1; 76 } 77 78 /* SUSP specific entries here */ 79 if ((r = cd9660_susp_initialize_node(diskStructure, node)) < 0) 80 return r; 81 82 /* currently called cd9660node_rrip_init_links */ 83 r = cd9660_rrip_initialize_node(diskStructure, node, parent, grandparent); 84 if (r < 0) 85 return r; 86 87 /* 88 * See if we need a CE record, and set all of the 89 * associated counters. 90 * 91 * This should be called after all extensions. After 92 * this is called, no new records should be added. 93 */ 94 if ((r = cd9660_susp_handle_continuation(diskStructure, node)) < 0) 95 return r; 96 97 /* Recurse on children. */ 98 TAILQ_FOREACH(cn, &node->cn_children, cn_next_child) { 99 if ((r = cd9660_susp_initialize(diskStructure, cn, node, parent)) < 0) 100 return 0; 101 } 102 return 1; 103 } 104 105 int 106 cd9660_susp_finalize(iso9660_disk *diskStructure, cd9660node *node) 107 { 108 cd9660node *temp; 109 struct inode_map_node *mapnode, *mapnodetmp; 110 int r; 111 112 assert(node != NULL); 113 114 if (node == diskStructure->rootNode) 115 diskStructure->susp_continuation_area_current_free = 0; 116 117 if ((r = cd9660_susp_finalize_node(diskStructure, node)) < 0) 118 return r; 119 if ((r = cd9660_rrip_finalize_node(node)) < 0) 120 return r; 121 122 TAILQ_FOREACH(temp, &node->cn_children, cn_next_child) { 123 if ((r = cd9660_susp_finalize(diskStructure, temp)) < 0) 124 return r; 125 } 126 127 if (diskStructure->rr_inode_next != 0) { 128 RB_FOREACH_SAFE(mapnode, inode_map_tree, 129 &(diskStructure->rr_inode_map), mapnodetmp) { 130 RB_REMOVE(inode_map_tree, 131 &(diskStructure->rr_inode_map), mapnode); 132 free(mapnode); 133 } 134 diskStructure->rr_inode_next = 0; 135 } 136 return 1; 137 } 138 139 /* 140 * If we really wanted to speed things up, we could have some sort of 141 * lookup table on the SUSP entry type that calls a functor. Or, we could 142 * combine the functions. These functions are kept separate to allow 143 * easier addition of other extensions. 144 145 * For the sake of simplicity and clarity, we won't be doing that for now. 146 */ 147 148 /* 149 * SUSP needs to update the following types: 150 * CE (continuation area) 151 */ 152 int 153 cd9660_susp_finalize_node(iso9660_disk *diskStructure, cd9660node *node) 154 { 155 struct ISO_SUSP_ATTRIBUTES *t; 156 157 /* Handle CE counters */ 158 if (node->susp_entry_ce_length > 0) { 159 node->susp_entry_ce_start = 160 diskStructure->susp_continuation_area_current_free; 161 diskStructure->susp_continuation_area_current_free += 162 node->susp_entry_ce_length; 163 } 164 165 TAILQ_FOREACH(t, &node->head, rr_ll) { 166 if (t->susp_type != SUSP_TYPE_SUSP || 167 t->entry_type != SUSP_ENTRY_SUSP_CE) 168 continue; 169 cd9660_bothendian_dword( 170 diskStructure-> 171 susp_continuation_area_start_sector, 172 t->attr.su_entry.CE.ca_sector); 173 174 cd9660_bothendian_dword( 175 diskStructure-> 176 susp_continuation_area_start_sector, 177 t->attr.su_entry.CE.ca_sector); 178 cd9660_bothendian_dword(node->susp_entry_ce_start, 179 t->attr.su_entry.CE.offset); 180 cd9660_bothendian_dword(node->susp_entry_ce_length, 181 t->attr.su_entry.CE.length); 182 } 183 return 0; 184 } 185 186 int 187 cd9660_rrip_finalize_node(cd9660node *node) 188 { 189 struct ISO_SUSP_ATTRIBUTES *t; 190 191 TAILQ_FOREACH(t, &node->head, rr_ll) { 192 if (t->susp_type != SUSP_TYPE_RRIP) 193 continue; 194 switch (t->entry_type) { 195 case SUSP_ENTRY_RRIP_CL: 196 /* Look at rr_relocated*/ 197 if (node->rr_relocated == NULL) 198 return -1; 199 cd9660_bothendian_dword( 200 node->rr_relocated->fileDataSector, 201 (unsigned char *) 202 t->attr.rr_entry.CL.dir_loc); 203 break; 204 case SUSP_ENTRY_RRIP_PL: 205 /* Look at rr_real_parent */ 206 if (node->parent == NULL || 207 node->parent->rr_real_parent == NULL) 208 return -1; 209 cd9660_bothendian_dword( 210 node->parent->rr_real_parent->fileDataSector, 211 (unsigned char *) 212 t->attr.rr_entry.PL.dir_loc); 213 break; 214 } 215 } 216 return 0; 217 } 218 219 static int 220 cd9660_susp_handle_continuation_common(iso9660_disk *diskStructure, 221 cd9660node *node, int space) 222 { 223 int ca_used, susp_used, susp_used_pre_ce, working; 224 struct ISO_SUSP_ATTRIBUTES *temp, *pre_ce, *last, *CE, *ST; 225 226 pre_ce = last = NULL; 227 working = 254 - space; 228 if (node->su_tail_size > 0) 229 /* Allow 4 bytes for "ST" record. */ 230 working -= node->su_tail_size + 4; 231 /* printf("There are %i bytes to work with\n",working); */ 232 233 susp_used_pre_ce = susp_used = 0; 234 ca_used = 0; 235 TAILQ_FOREACH(temp, &node->head, rr_ll) { 236 if (working < 0) 237 break; 238 /* 239 * printf("SUSP Entry found, length is %i\n", 240 * CD9660_SUSP_ENTRY_SIZE(temp)); 241 */ 242 working -= CD9660_SUSP_ENTRY_SIZE(temp); 243 if (working >= 0) { 244 last = temp; 245 susp_used += CD9660_SUSP_ENTRY_SIZE(temp); 246 } 247 if (working >= 28) { 248 /* 249 * Remember the last entry after which we 250 * could insert a "CE" entry. 251 */ 252 pre_ce = last; 253 susp_used_pre_ce = susp_used; 254 } 255 } 256 257 /* A CE entry is needed */ 258 if (working <= 0) { 259 CE = cd9660node_susp_create_node(SUSP_TYPE_SUSP, 260 SUSP_ENTRY_SUSP_CE, "CE", SUSP_LOC_ENTRY); 261 cd9660_susp_ce(CE, node); 262 /* This will automatically insert at the appropriate location */ 263 if (pre_ce != NULL) 264 TAILQ_INSERT_AFTER(&node->head, pre_ce, CE, rr_ll); 265 else 266 TAILQ_INSERT_HEAD(&node->head, CE, rr_ll); 267 last = CE; 268 susp_used = susp_used_pre_ce + 28; 269 /* Count how much CA data is necessary */ 270 for (temp = TAILQ_NEXT(last, rr_ll); temp != NULL; 271 temp = TAILQ_NEXT(temp, rr_ll)) { 272 ca_used += CD9660_SUSP_ENTRY_SIZE(temp); 273 } 274 } 275 276 /* An ST entry is needed */ 277 if (node->su_tail_size > 0) { 278 ST = cd9660node_susp_create_node(SUSP_TYPE_SUSP, 279 SUSP_ENTRY_SUSP_ST, "ST", SUSP_LOC_ENTRY); 280 cd9660_susp_st(ST, node); 281 if (last != NULL) 282 TAILQ_INSERT_AFTER(&node->head, last, ST, rr_ll); 283 else 284 TAILQ_INSERT_HEAD(&node->head, ST, rr_ll); 285 last = ST; 286 susp_used += 4; 287 } 288 if (last != NULL) 289 last->last_in_suf = 1; 290 291 node->susp_entry_size = susp_used; 292 node->susp_entry_ce_length = ca_used; 293 294 diskStructure->susp_continuation_area_size += ca_used; 295 return 1; 296 } 297 298 /* See if a continuation entry is needed for each of the different types */ 299 static int 300 cd9660_susp_handle_continuation(iso9660_disk *diskStructure, cd9660node *node) 301 { 302 assert (node != NULL); 303 304 /* Entry */ 305 if (cd9660_susp_handle_continuation_common(diskStructure, 306 node,(int)(node->isoDirRecord->length[0])) < 0) 307 return 0; 308 309 return 1; 310 } 311 312 int 313 cd9660_susp_initialize_node(iso9660_disk *diskStructure, cd9660node *node) 314 { 315 struct ISO_SUSP_ATTRIBUTES *temp; 316 317 /* 318 * Requirements/notes: 319 * CE: is added for us where needed 320 * ST: not sure if it is even required, but if so, should be 321 * handled by the CE code 322 * PD: isn't needed (though might be added for testing) 323 * SP: is stored ONLY on the . record of the root directory 324 * ES: not sure 325 */ 326 327 /* Check for root directory, add SP and ER if needed. */ 328 if (node->type & CD9660_TYPE_DOT) { 329 if (node->parent == diskStructure->rootNode) { 330 temp = cd9660node_susp_create_node(SUSP_TYPE_SUSP, 331 SUSP_ENTRY_SUSP_SP, "SP", SUSP_LOC_DOT); 332 cd9660_susp_sp(temp, node); 333 334 /* Should be first entry. */ 335 TAILQ_INSERT_HEAD(&node->head, temp, rr_ll); 336 } 337 } 338 return 1; 339 } 340 341 static void 342 cd9660_rrip_initialize_inode(iso9660_disk *diskStructure, cd9660node *node) 343 { 344 struct ISO_SUSP_ATTRIBUTES *attr; 345 346 /* 347 * Inode dependent values - this may change, 348 * but for now virtual files and directories do 349 * not have an inode structure 350 */ 351 352 if ((node->node != NULL) && (node->node->inode != NULL)) { 353 /* PX - POSIX attributes */ 354 attr = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 355 SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY); 356 cd9660node_rrip_px(diskStructure, attr, node->node); 357 358 TAILQ_INSERT_TAIL(&node->head, attr, rr_ll); 359 360 /* TF - timestamp */ 361 attr = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 362 SUSP_ENTRY_RRIP_TF, "TF", SUSP_LOC_ENTRY); 363 cd9660node_rrip_tf(attr, node->node); 364 TAILQ_INSERT_TAIL(&node->head, attr, rr_ll); 365 366 /* SL - Symbolic link */ 367 /* ?????????? Dan - why is this here? */ 368 if (TAILQ_EMPTY(&node->cn_children) && 369 node->node->inode != NULL && 370 S_ISLNK(node->node->inode->st.st_mode)) 371 cd9660_createSL(node); 372 373 /* PN - device number */ 374 if (node->node->inode != NULL && 375 ((S_ISCHR(node->node->inode->st.st_mode) || 376 S_ISBLK(node->node->inode->st.st_mode)))) { 377 attr = 378 cd9660node_susp_create_node(SUSP_TYPE_RRIP, 379 SUSP_ENTRY_RRIP_PN, "PN", 380 SUSP_LOC_ENTRY); 381 cd9660node_rrip_pn(attr, node->node); 382 TAILQ_INSERT_TAIL(&node->head, attr, rr_ll); 383 } 384 } 385 } 386 387 int 388 cd9660_rrip_initialize_node(iso9660_disk *diskStructure, cd9660node *node, 389 cd9660node *parent, cd9660node *grandparent) 390 { 391 struct ISO_SUSP_ATTRIBUTES *current = NULL; 392 393 assert(node != NULL); 394 395 if (node->type & CD9660_TYPE_DOT) { 396 /* 397 * Handle ER - should be the only entry to appear on 398 * a "." record 399 */ 400 if (node->parent == diskStructure->rootNode) { 401 cd9660_susp_ER(node, 1, SUSP_RRIP_ER_EXT_ID, 402 SUSP_RRIP_ER_EXT_DES, SUSP_RRIP_ER_EXT_SRC); 403 } 404 if (parent != NULL && parent->node != NULL && 405 parent->node->inode != NULL) { 406 /* PX - POSIX attributes */ 407 current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 408 SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY); 409 cd9660node_rrip_px(diskStructure, current, 410 parent->node); 411 TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 412 413 /* TF - timestamp */ 414 current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 415 SUSP_ENTRY_RRIP_TF, "TF", SUSP_LOC_ENTRY); 416 cd9660node_rrip_tf(current, parent->node); 417 TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 418 } 419 } else if (node->type & CD9660_TYPE_DOTDOT) { 420 if (grandparent != NULL && grandparent->node != NULL && 421 grandparent->node->inode != NULL) { 422 /* PX - POSIX attributes */ 423 current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 424 SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY); 425 cd9660node_rrip_px(diskStructure, current, 426 grandparent->node); 427 TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 428 429 /* TF - timestamp */ 430 current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 431 SUSP_ENTRY_RRIP_TF, "TF", SUSP_LOC_ENTRY); 432 cd9660node_rrip_tf(current, grandparent->node); 433 TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 434 } 435 /* Handle PL */ 436 if (parent != NULL && parent->rr_real_parent != NULL) { 437 current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 438 SUSP_ENTRY_RRIP_PL, "PL", SUSP_LOC_DOTDOT); 439 cd9660_rrip_PL(current,node); 440 TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 441 } 442 } else { 443 cd9660_rrip_initialize_inode(diskStructure, node); 444 445 if (node == diskStructure->rr_moved_dir) { 446 cd9660_rrip_add_NM(node, RRIP_DEFAULT_MOVE_DIR_NAME); 447 } else if (node->node != NULL) { 448 cd9660_rrip_NM(node); 449 } 450 451 /* Rock ridge directory relocation code here. */ 452 453 /* First handle the CL for the placeholder file. */ 454 if (node->rr_relocated != NULL) { 455 current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 456 SUSP_ENTRY_RRIP_CL, "CL", SUSP_LOC_ENTRY); 457 cd9660_rrip_CL(current, node); 458 TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 459 } 460 461 /* Handle RE*/ 462 if (node->rr_real_parent != NULL) { 463 current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 464 SUSP_ENTRY_RRIP_RE, "RE", SUSP_LOC_ENTRY); 465 cd9660_rrip_RE(current,node); 466 TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 467 } 468 } 469 return 1; 470 } 471 472 struct ISO_SUSP_ATTRIBUTES* 473 cd9660node_susp_create_node(int susp_type, int entry_type, const char *type_id, 474 int write_loc) 475 { 476 struct ISO_SUSP_ATTRIBUTES* temp; 477 478 temp = emalloc(sizeof(*temp)); 479 temp->susp_type = susp_type; 480 temp->entry_type = entry_type; 481 temp->last_in_suf = 0; 482 /* Phase this out */ 483 temp->type_of[0] = type_id[0]; 484 temp->type_of[1] = type_id[1]; 485 temp->write_location = write_loc; 486 487 /* 488 * Since the first four bytes is common, lets go ahead and 489 * set the type identifier, since we are passing that to this 490 * function anyhow. 491 */ 492 temp->attr.su_entry.SP.h.type[0] = type_id[0]; 493 temp->attr.su_entry.SP.h.type[1] = type_id[1]; 494 return temp; 495 } 496 497 int 498 cd9660_rrip_PL(struct ISO_SUSP_ATTRIBUTES* p, cd9660node *node __unused) 499 { 500 p->attr.rr_entry.PL.h.length[0] = 12; 501 p->attr.rr_entry.PL.h.version[0] = 1; 502 return 1; 503 } 504 505 int 506 cd9660_rrip_CL(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *node __unused) 507 { 508 p->attr.rr_entry.CL.h.length[0] = 12; 509 p->attr.rr_entry.CL.h.version[0] = 1; 510 return 1; 511 } 512 513 int 514 cd9660_rrip_RE(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *node __unused) 515 { 516 p->attr.rr_entry.RE.h.length[0] = 4; 517 p->attr.rr_entry.RE.h.version[0] = 1; 518 return 1; 519 } 520 521 void 522 cd9660_createSL(cd9660node *node) 523 { 524 struct ISO_SUSP_ATTRIBUTES* current; 525 int path_count, dir_count, done, i, j, dir_copied; 526 char temp_cr[255]; 527 char temp_sl[255]; /* used in copying continuation entry*/ 528 char* sl_ptr; 529 530 sl_ptr = node->node->symlink; 531 532 done = 0; 533 path_count = 0; 534 dir_count = 0; 535 dir_copied = 0; 536 current = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 537 SUSP_ENTRY_RRIP_SL, "SL", SUSP_LOC_ENTRY); 538 539 current->attr.rr_entry.SL.h.version[0] = 1; 540 current->attr.rr_entry.SL.flags[0] = SL_FLAGS_NONE; 541 542 if (*sl_ptr == '/') { 543 temp_cr[0] = SL_FLAGS_ROOT; 544 temp_cr[1] = 0; 545 memcpy(current->attr.rr_entry.SL.component + path_count, 546 temp_cr, 2); 547 path_count += 2; 548 sl_ptr++; 549 } 550 551 for (i = 0; i < (dir_count + 2); i++) 552 temp_cr[i] = '\0'; 553 554 while (!done) { 555 while ((*sl_ptr != '/') && (*sl_ptr != '\0')) { 556 dir_copied = 1; 557 if (*sl_ptr == '.') { 558 if ((*(sl_ptr + 1) == '/') || (*(sl_ptr + 1) 559 == '\0')) { 560 temp_cr[0] = SL_FLAGS_CURRENT; 561 sl_ptr++; 562 } else if(*(sl_ptr + 1) == '.') { 563 if ((*(sl_ptr + 2) == '/') || 564 (*(sl_ptr + 2) == '\0')) { 565 temp_cr[0] = SL_FLAGS_PARENT; 566 sl_ptr += 2; 567 } 568 } else { 569 temp_cr[dir_count+2] = *sl_ptr; 570 sl_ptr++; 571 dir_count++; 572 } 573 } else { 574 temp_cr[dir_count + 2] = *sl_ptr; 575 sl_ptr++; 576 dir_count++; 577 } 578 } 579 580 if ((path_count + dir_count) >= 249) { 581 current->attr.rr_entry.SL.flags[0] |= SL_FLAGS_CONTINUE; 582 583 j = 0; 584 585 if (path_count <= 249) { 586 while(j != (249 - path_count)) { 587 temp_sl[j] = temp_cr[j]; 588 j++; 589 } 590 temp_sl[0] = SL_FLAGS_CONTINUE; 591 temp_sl[1] = j - 2; 592 memcpy( 593 current->attr.rr_entry.SL.component + 594 path_count, 595 temp_sl, j); 596 } 597 598 path_count += j; 599 current->attr.rr_entry.SL.h.length[0] = path_count + 5; 600 TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 601 current= cd9660node_susp_create_node(SUSP_TYPE_RRIP, 602 SUSP_ENTRY_RRIP_SL, "SL", SUSP_LOC_ENTRY); 603 current->attr.rr_entry.SL.h.version[0] = 1; 604 current->attr.rr_entry.SL.flags[0] = SL_FLAGS_NONE; 605 606 path_count = 0; 607 608 if (dir_count > 2) { 609 while (j != dir_count + 2) { 610 current->attr.rr_entry.SL.component[ 611 path_count + 2] = temp_cr[j]; 612 j++; 613 path_count++; 614 } 615 current->attr.rr_entry.SL.component[1] 616 = path_count; 617 path_count+= 2; 618 } else { 619 while(j != dir_count) { 620 current->attr.rr_entry.SL.component[ 621 path_count+2] = temp_cr[j]; 622 j++; 623 path_count++; 624 } 625 } 626 } else { 627 if (dir_copied == 1) { 628 temp_cr[1] = dir_count; 629 memcpy(current->attr.rr_entry.SL.component + 630 path_count, 631 temp_cr, dir_count + 2); 632 path_count += dir_count + 2; 633 } 634 } 635 636 if (*sl_ptr == '\0') { 637 done = 1; 638 current->attr.rr_entry.SL.h.length[0] = path_count + 5; 639 TAILQ_INSERT_TAIL(&node->head, current, rr_ll); 640 } else { 641 sl_ptr++; 642 dir_count = 0; 643 dir_copied = 0; 644 for(i = 0; i < 255; i++) { 645 temp_cr[i] = '\0'; 646 } 647 } 648 } 649 } 650 651 static int 652 inode_map_node_cmp(struct inode_map_node *a, struct inode_map_node *b) 653 { 654 if (a->key < b->key) 655 return (-1); 656 if (a->key > b->key) 657 return (1); 658 return (0); 659 } 660 661 RB_GENERATE(inode_map_tree, inode_map_node, entry, inode_map_node_cmp); 662 663 static uint64_t 664 inode_map(iso9660_disk *diskStructure, uint64_t in) 665 { 666 struct inode_map_node lookup = { .key = in }; 667 struct inode_map_node *node; 668 669 /* 670 * Always assign an inode number if src inode unset. mtree mode leaves 671 * src inode unset for files with st_nlink == 1. 672 */ 673 if (in != 0) { 674 node = RB_FIND(inode_map_tree, &(diskStructure->rr_inode_map), 675 &lookup); 676 if (node != NULL) 677 return (node->value); 678 } 679 680 node = emalloc(sizeof(struct inode_map_node)); 681 node->key = in; 682 node->value = diskStructure->rr_inode_next++; 683 RB_INSERT(inode_map_tree, &(diskStructure->rr_inode_map), node); 684 return (node->value); 685 } 686 687 int 688 cd9660node_rrip_px(iso9660_disk *diskStructure, struct ISO_SUSP_ATTRIBUTES *v, 689 fsnode *pxinfo) 690 { 691 v->attr.rr_entry.PX.h.length[0] = 44; 692 v->attr.rr_entry.PX.h.version[0] = 1; 693 cd9660_bothendian_dword(pxinfo->inode->st.st_mode, 694 v->attr.rr_entry.PX.mode); 695 cd9660_bothendian_dword(pxinfo->inode->st.st_nlink, 696 v->attr.rr_entry.PX.links); 697 cd9660_bothendian_dword(pxinfo->inode->st.st_uid, 698 v->attr.rr_entry.PX.uid); 699 cd9660_bothendian_dword(pxinfo->inode->st.st_gid, 700 v->attr.rr_entry.PX.gid); 701 cd9660_bothendian_dword(inode_map(diskStructure, 702 pxinfo->inode->st.st_ino), v->attr.rr_entry.PX.serial); 703 704 return 1; 705 } 706 707 int 708 cd9660node_rrip_pn(struct ISO_SUSP_ATTRIBUTES *pn_field, fsnode *fnode) 709 { 710 pn_field->attr.rr_entry.PN.h.length[0] = 20; 711 pn_field->attr.rr_entry.PN.h.version[0] = 1; 712 713 if (sizeof (fnode->inode->st.st_rdev) > 4) 714 cd9660_bothendian_dword( 715 (uint64_t)fnode->inode->st.st_rdev >> 32, 716 pn_field->attr.rr_entry.PN.high); 717 else 718 cd9660_bothendian_dword(0, pn_field->attr.rr_entry.PN.high); 719 720 cd9660_bothendian_dword(fnode->inode->st.st_rdev & 0xffffffff, 721 pn_field->attr.rr_entry.PN.low); 722 return 1; 723 } 724 725 #if 0 726 int 727 cd9660node_rrip_nm(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *file_node) 728 { 729 int nm_length = strlen(file_node->isoDirRecord->name) + 5; 730 p->attr.rr_entry.NM.h.type[0] = 'N'; 731 p->attr.rr_entry.NM.h.type[1] = 'M'; 732 sprintf(p->attr.rr_entry.NM.altname, "%s", file_node->isoDirRecord->name); 733 p->attr.rr_entry.NM.h.length[0] = (unsigned char)nm_length; 734 p->attr.rr_entry.NM.h.version[0] = (unsigned char)1; 735 p->attr.rr_entry.NM.flags[0] = (unsigned char) NM_PARENT; 736 return 1; 737 } 738 #endif 739 740 int 741 cd9660node_rrip_tf(struct ISO_SUSP_ATTRIBUTES *p, fsnode *_node) 742 { 743 p->attr.rr_entry.TF.flags[0] = TF_MODIFY | TF_ACCESS | TF_ATTRIBUTES; 744 p->attr.rr_entry.TF.h.length[0] = 5; 745 p->attr.rr_entry.TF.h.version[0] = 1; 746 747 /* 748 * Need to add creation time, backup time, 749 * expiration time, and effective time. 750 */ 751 752 cd9660_time_915(p->attr.rr_entry.TF.timestamp, 753 _node->inode->st.st_mtime); 754 p->attr.rr_entry.TF.h.length[0] += 7; 755 756 cd9660_time_915(p->attr.rr_entry.TF.timestamp + 7, 757 _node->inode->st.st_atime); 758 p->attr.rr_entry.TF.h.length[0] += 7; 759 760 cd9660_time_915(p->attr.rr_entry.TF.timestamp + 14, 761 _node->inode->st.st_ctime); 762 p->attr.rr_entry.TF.h.length[0] += 7; 763 return 1; 764 } 765 766 int 767 cd9660_susp_sp(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *spinfo __unused) 768 { 769 p->attr.su_entry.SP.h.length[0] = 7; 770 p->attr.su_entry.SP.h.version[0] = 1; 771 p->attr.su_entry.SP.check[0] = 0xBE; 772 p->attr.su_entry.SP.check[1] = 0xEF; 773 p->attr.su_entry.SP.len_skp[0] = 0; 774 return 1; 775 } 776 777 int 778 cd9660_susp_st(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *stinfo __unused) 779 { 780 p->attr.su_entry.ST.h.type[0] = 'S'; 781 p->attr.su_entry.ST.h.type[1] = 'T'; 782 p->attr.su_entry.ST.h.length[0] = 4; 783 p->attr.su_entry.ST.h.version[0] = 1; 784 return 1; 785 } 786 787 int 788 cd9660_susp_ce(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *spinfo __unused) 789 { 790 p->attr.su_entry.CE.h.length[0] = 28; 791 p->attr.su_entry.CE.h.version[0] = 1; 792 /* Other attributes dont matter right now, will be updated later */ 793 return 1; 794 } 795 796 int 797 cd9660_susp_pd(struct ISO_SUSP_ATTRIBUTES *p __unused, int length __unused) 798 { 799 return 1; 800 } 801 802 void 803 cd9660_rrip_add_NM(cd9660node *node, const char *name) 804 { 805 int working,len; 806 const char *p; 807 struct ISO_SUSP_ATTRIBUTES *r; 808 809 /* 810 * Each NM record has 254 bytes to work with. This means that 811 * the name data itself only has 249 bytes to work with. So, a 812 * name with 251 characters would require two nm records. 813 */ 814 p = name; 815 working = 1; 816 while (working) { 817 r = cd9660node_susp_create_node(SUSP_TYPE_RRIP, 818 SUSP_ENTRY_RRIP_NM, "NM", SUSP_LOC_ENTRY); 819 r->attr.rr_entry.NM.h.version[0] = 1; 820 r->attr.rr_entry.NM.flags[0] = RRIP_NM_FLAGS_NONE; 821 len = strlen(p); 822 823 if (len > 249) { 824 len = 249; 825 r->attr.rr_entry.NM.flags[0] = RRIP_NM_FLAGS_CONTINUE; 826 } else { 827 working = 0; 828 } 829 memcpy(r->attr.rr_entry.NM.altname, p, len); 830 r->attr.rr_entry.NM.h.length[0] = 5 + len; 831 832 TAILQ_INSERT_TAIL(&node->head, r, rr_ll); 833 834 p += len; 835 } 836 } 837 838 void 839 cd9660_rrip_NM(cd9660node *node) 840 { 841 cd9660_rrip_add_NM(node, node->node->name); 842 } 843 844 struct ISO_SUSP_ATTRIBUTES* 845 cd9660_susp_ER(cd9660node *node, 846 u_char ext_version, const char* ext_id, const char* ext_des, 847 const char* ext_src) 848 { 849 int l; 850 struct ISO_SUSP_ATTRIBUTES *r; 851 852 r = cd9660node_susp_create_node(SUSP_TYPE_SUSP, 853 SUSP_ENTRY_SUSP_ER, "ER", SUSP_LOC_DOT); 854 855 /* Fixed data is 8 bytes */ 856 r->attr.su_entry.ER.h.length[0] = 8; 857 r->attr.su_entry.ER.h.version[0] = 1; 858 859 r->attr.su_entry.ER.len_id[0] = (u_char)strlen(ext_id); 860 r->attr.su_entry.ER.len_des[0] = (u_char)strlen(ext_des); 861 r->attr.su_entry.ER.len_src[0] = (u_char)strlen(ext_src); 862 863 l = r->attr.su_entry.ER.len_id[0] + 864 r->attr.su_entry.ER.len_src[0] + 865 r->attr.su_entry.ER.len_des[0]; 866 867 /* Everything must fit. */ 868 assert(l + r->attr.su_entry.ER.h.length[0] <= 254); 869 870 r->attr.su_entry.ER.h.length[0] += (u_char)l; 871 872 873 r->attr.su_entry.ER.ext_ver[0] = ext_version; 874 memcpy(r->attr.su_entry.ER.ext_data, ext_id, 875 (int)r->attr.su_entry.ER.len_id[0]); 876 l = (int) r->attr.su_entry.ER.len_id[0]; 877 memcpy(r->attr.su_entry.ER.ext_data + l,ext_des, 878 (int)r->attr.su_entry.ER.len_des[0]); 879 880 l += (int)r->attr.su_entry.ER.len_des[0]; 881 memcpy(r->attr.su_entry.ER.ext_data + l,ext_src, 882 (int)r->attr.su_entry.ER.len_src[0]); 883 884 TAILQ_INSERT_TAIL(&node->head, r, rr_ll); 885 return r; 886 } 887 888 struct ISO_SUSP_ATTRIBUTES* 889 cd9660_susp_ES(struct ISO_SUSP_ATTRIBUTES *last __unused, cd9660node *node __unused) 890 { 891 return NULL; 892 } 893