1 /* 2 * File tree.c - scan directory tree and build memory structures for iso9660 3 * filesystem 4 5 Written by Eric Youngdale (1993). 6 7 Copyright 1993 Yggdrasil Computing, Incorporated 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2, or (at your option) 12 any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 22 23 /* ADD_FILES changes made by Ross Biro biro (at) yggdrasil.com 2/23/95 */ 24 25 /* APPLE_HYB James Pearson j.pearson (at) ge.ucl.ac.uk 16/3/1999 */ 26 27 #include <stdlib.h> 28 #include <string.h> 29 #include <time.h> 30 #include <errno.h> 31 32 #include "config.h" 33 #include "apple_proto.h" 34 35 #ifndef VMS 36 #if defined(MAJOR_IN_SYSMACROS) 37 #include <sys/sysmacros.h> 38 #endif 39 40 #ifdef HAVE_UNISTD_H 41 #include <unistd.h> 42 #endif 43 #include <fctldefs.h> 44 45 #if defined(MAJOR_IN_MKDEV) 46 #include <sys/types.h> 47 #include <sys/mkdev.h> 48 #endif 49 #else 50 #include <sys/file.h> 51 #include <vms/fabdef.h> 52 #include "vms.h" 53 extern char * strdup(const char *); 54 #endif 55 56 /* 57 * Autoconf should be able to figure this one out for us and let us know 58 * whether the system has memmove or not. 59 */ 60 # ifndef HAVE_MEMMOVE 61 # define memmove(d, s, n) bcopy ((s), (d), (n)) 62 # endif 63 64 #include "mkisofs.h" 65 #include "iso9660.h" 66 #include "match.h" 67 68 #include <sys/stat.h> 69 70 #ifdef DOESNT_WORK 71 72 #ifdef NON_UNIXFS 73 #define S_ISLNK(m) (0) 74 #define S_ISSOCK(m) (0) 75 #define S_ISFIFO(m) (0) 76 #else 77 #ifndef S_ISLNK 78 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) 79 #endif 80 #ifndef S_ISSOCK 81 # ifdef S_IFSOCK 82 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) 83 # else 84 # define S_ISSOCK(m) (0) 85 # endif 86 #endif 87 #endif 88 89 #else 90 #include <statdefs.h> 91 #endif 92 93 94 #ifdef __SVR4 95 extern char * strdup(const char *); 96 #endif 97 98 static unsigned char symlink_buff[256]; 99 100 static void stat_fix __PR((struct stat * st)); 101 static void generate_reloc_directory __PR((void)); 102 103 static void DECL(attach_dot_entries, (struct directory * dirnode, 104 struct stat * parent_stat)); 105 static void DECL(delete_directory, (struct directory * parent, struct directory * child)); 106 107 extern int verbose; 108 109 struct stat fstatbuf = {0,}; /* We use this for the artificial entries we create */ 110 111 struct stat root_statbuf = {0, }; /* Stat buffer for root directory */ 112 113 struct directory * reloc_dir = NULL; 114 115 static void 116 FDECL1(stat_fix, struct stat *, st) 117 { 118 /* Remove the uid and gid, they will only be useful on the author's 119 system. */ 120 st->st_uid = 0; 121 st->st_gid = 0; 122 123 /* 124 * Make sure the file modes make sense. Turn on all read bits. Turn 125 * on all exec/search bits if any exec/search bit is set. Turn off 126 * all write bits, and all special mode bits (on a r/o fs lock bits 127 * are useless, and with uid+gid 0 don't want set-id bits, either). 128 */ 129 st->st_mode |= 0444; 130 #ifndef _WIN32 /* make all file "executable" */ 131 if (st->st_mode & 0111) 132 #endif /* _WIN32 */ 133 st->st_mode |= 0111; 134 st->st_mode &= ~07222; 135 } 136 137 int 138 FDECL2(stat_filter, char *, path, struct stat *, st) 139 { 140 int result = stat(path, st); 141 if (result >= 0 && rationalize) 142 stat_fix(st); 143 return result; 144 } 145 146 int 147 FDECL2(lstat_filter, char *, path, struct stat *, st) 148 { 149 int result = lstat(path, st); 150 if (result >= 0 && rationalize) 151 stat_fix(st); 152 return result; 153 } 154 155 static int FDECL1(sort_n_finish, struct directory *, this_dir) 156 { 157 struct directory_entry * s_entry; 158 struct directory_entry * s_entry1; 159 struct directory_entry * table; 160 int count; 161 int d1; 162 int d2; 163 int d3; 164 int new_reclen; 165 char * c; 166 int status = 0; 167 int tablesize = 0; 168 char newname[34]; 169 char rootname[34]; 170 171 /* Here we can take the opportunity to toss duplicate entries from the 172 directory. */ 173 174 /* ignore if it's hidden */ 175 if(this_dir->dir_flags & INHIBIT_ISO9660_ENTRY) 176 { 177 return 0; 178 } 179 180 table = NULL; 181 182 init_fstatbuf(); 183 184 /* 185 * If we had artificially created this directory, then we might be 186 * missing the required '.' entries. Create these now if we need 187 * them. 188 */ 189 if( (this_dir->dir_flags & (DIR_HAS_DOT | DIR_HAS_DOTDOT)) != 190 (DIR_HAS_DOT | DIR_HAS_DOTDOT) ) 191 { 192 attach_dot_entries(this_dir, &fstatbuf); 193 } 194 195 flush_file_hash(); 196 s_entry = this_dir->contents; 197 while(s_entry) 198 { 199 /* ignore if it's hidden */ 200 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) 201 { 202 s_entry = s_entry->next; 203 continue; 204 } 205 206 /* 207 * First assume no conflict, and handle this case 208 */ 209 if(!(s_entry1 = find_file_hash(s_entry->isorec.name))) 210 { 211 add_file_hash(s_entry); 212 s_entry = s_entry->next; 213 continue; 214 } 215 216 #ifdef APPLE_HYB 217 /* if the pair are associated, then skip (as they have the same name!) */ 218 if(apple_both && s_entry1->assoc && s_entry1->assoc == s_entry) 219 { 220 s_entry = s_entry->next; 221 continue; 222 } 223 #endif /* APPLE_HYB */ 224 225 if(s_entry1 == s_entry) 226 { 227 fprintf(stderr,"Fatal goof\n"); 228 exit(1); 229 } 230 231 /* 232 * OK, handle the conflicts. Try substitute names until we come 233 * up with a winner 234 */ 235 strcpy(rootname, s_entry->isorec.name); 236 if(full_iso9660_filenames) 237 { 238 if(strlen(rootname) > 27) rootname[27] = 0; 239 } 240 241 /* 242 * Strip off the non-significant part of the name so that we are left 243 * with a sensible root filename. If we don't find a '.', then try 244 * a ';'. 245 */ 246 c = strchr(rootname, '.'); 247 if (c) 248 *c = 0; 249 else 250 { 251 c = strchr(rootname, ';'); 252 if (c) *c = 0; 253 } 254 for(d1 = 0; d1 < 36; d1++) 255 { 256 for(d2 = 0; d2 < 36; d2++) 257 { 258 for(d3 = 0; d3 < 36; d3++) 259 { 260 snprintf(newname, sizeof newname, "%s.%c%c%c%s", rootname, 261 (d1 <= 9 ? '0' + d1 : 'A' + d1 - 10), 262 (d2 <= 9 ? '0' + d2 : 'A' + d2 - 10), 263 (d3 <= 9 ? '0' + d3 : 'A' + d3 - 10), 264 (s_entry->isorec.flags[0] == 2 || 265 omit_version_number ? "" : ";1")); 266 267 #ifdef VMS 268 /* Sigh. VAXCRTL seems to be broken here */ 269 { 270 int ijk = 0; 271 while(newname[ijk]) 272 { 273 if(newname[ijk] == ' ') newname[ijk] = '0'; 274 ijk++; 275 } 276 } 277 #endif 278 279 if(!find_file_hash(newname)) goto got_valid_name; 280 } 281 } 282 } 283 284 /* 285 * If we fell off the bottom here, we were in real trouble. 286 */ 287 fprintf(stderr,"Unable to generate unique name for file %s\n", s_entry->name); 288 exit(1); 289 290 got_valid_name: 291 /* 292 * OK, now we have a good replacement name. Now decide which one 293 * of these two beasts should get the name changed 294 */ 295 if(s_entry->priority < s_entry1->priority) 296 { 297 if( verbose > 0 ) 298 { 299 fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname, 300 this_dir->whole_name, SPATH_SEPARATOR, 301 s_entry->name, s_entry1->name); 302 } 303 s_entry->isorec.name_len[0] = strlen(newname); 304 new_reclen = sizeof(struct iso_directory_record) - 305 sizeof(s_entry->isorec.name) + 306 strlen(newname); 307 if(use_RockRidge) 308 { 309 if (new_reclen & 1) new_reclen++; /* Pad to an even byte */ 310 new_reclen += s_entry->rr_attr_size; 311 } 312 if (new_reclen & 1) new_reclen++; /* Pad to an even byte */ 313 s_entry->isorec.length[0] = new_reclen; 314 strcpy(s_entry->isorec.name, newname); 315 #ifdef APPLE_HYB 316 /* has resource fork - needs new name */ 317 if (apple_both && s_entry->assoc) { 318 struct directory_entry *s_entry2 = s_entry->assoc; 319 320 /* resource fork name *should* be the same as the data fork */ 321 s_entry2->isorec.name_len[0] = s_entry->isorec.name_len[0]; 322 strcpy(s_entry2->isorec.name, s_entry->isorec.name); 323 s_entry2->isorec.length[0] = new_reclen; 324 } 325 #endif /* APPLE_HYB */ 326 } 327 else 328 { 329 delete_file_hash(s_entry1); 330 if( verbose > 0 ) 331 { 332 fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname, 333 this_dir->whole_name, SPATH_SEPARATOR, 334 s_entry1->name, s_entry->name); 335 } 336 s_entry1->isorec.name_len[0] = strlen(newname); 337 new_reclen = sizeof(struct iso_directory_record) - 338 sizeof(s_entry1->isorec.name) + 339 strlen(newname); 340 if(use_RockRidge) 341 { 342 if (new_reclen & 1) new_reclen++; /* Pad to an even byte */ 343 new_reclen += s_entry1->rr_attr_size; 344 } 345 if (new_reclen & 1) new_reclen++; /* Pad to an even byte */ 346 s_entry1->isorec.length[0] = new_reclen; 347 strcpy(s_entry1->isorec.name, newname); 348 add_file_hash(s_entry1); 349 #ifdef APPLE_HYB 350 /* has resource fork - needs new name */ 351 if (apple_both && s_entry1->assoc) { 352 struct directory_entry *s_entry2 = s_entry1->assoc; 353 354 /* resource fork name *should* be the same as the data fork */ 355 s_entry2->isorec.name_len[0] = s_entry1->isorec.name_len[0]; 356 strcpy(s_entry2->isorec.name, s_entry1->isorec.name); 357 s_entry2->isorec.length[0] = new_reclen; 358 } 359 #endif /* APPLE_HYB */ 360 } 361 add_file_hash(s_entry); 362 s_entry = s_entry->next; 363 } 364 365 if(generate_tables 366 #ifdef APPLE_HYB 367 && !find_file_hash(trans_tbl) 368 #else 369 && !find_file_hash("TRANS.TBL") 370 #endif /* APPLE_HYB */ 371 && (reloc_dir != this_dir) 372 && (this_dir->extent == 0) ) 373 { 374 /* 375 * First we need to figure out how big this table is 376 */ 377 for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) 378 { 379 if(strcmp(s_entry->name, ".") == 0 || 380 strcmp(s_entry->name, "..") == 0) continue; 381 #ifdef APPLE_HYB 382 /* skip table entry for the resource fork */ 383 if(apple_both && (s_entry->isorec.flags[0] & ASSOC_FLAG)) 384 continue; 385 #endif /* APPLE_HYB */ 386 if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY) continue; 387 if(s_entry->table) tablesize += 35 + strlen(s_entry->table); 388 } 389 } 390 391 if( tablesize > 0 ) 392 { 393 table = (struct directory_entry *) 394 e_malloc(sizeof (struct directory_entry)); 395 memset(table, 0, sizeof(struct directory_entry)); 396 table->table = NULL; 397 table->next = this_dir->contents; 398 this_dir->contents = table; 399 400 table->filedir = root; 401 table->isorec.flags[0] = 0; 402 table->priority = 32768; 403 iso9660_date(table->isorec.date, fstatbuf.st_mtime); 404 table->inode = TABLE_INODE; 405 table->dev = (dev_t) UNCACHED_DEVICE; 406 set_723(table->isorec.volume_sequence_number, volume_sequence_number); 407 set_733((char *) table->isorec.size, tablesize); 408 table->size = tablesize; 409 table->filedir = this_dir; 410 if (jhide_trans_tbl) 411 table->de_flags |= INHIBIT_JOLIET_ENTRY; 412 table->name = strdup("<translation table>"); 413 table->table = (char *) e_malloc(ROUND_UP(tablesize)+1); 414 memset(table->table, 0, ROUND_UP(tablesize)+1); 415 #ifdef APPLE_HYB 416 iso9660_file_length (trans_tbl, table, 0); 417 #else 418 iso9660_file_length ("TRANS.TBL", table, 0); 419 #endif /* APPLE_HYB */ 420 421 if(use_RockRidge) 422 { 423 fstatbuf.st_mode = 0444 | S_IFREG; 424 fstatbuf.st_nlink = 1; 425 generate_rock_ridge_attributes("", 426 #ifdef APPLE_HYB 427 trans_tbl, table, 428 #else 429 "TRANS.TBL", table, 430 #endif /* APPLE_HYB */ 431 &fstatbuf, &fstatbuf, 0); 432 } 433 } 434 435 /* 436 * We have now chosen the 8.3 names and we should now know the length 437 * of every entry in the directory. 438 */ 439 for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) 440 { 441 /* skip if it's hidden */ 442 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) 443 { 444 continue; 445 } 446 447 new_reclen = strlen(s_entry->isorec.name); 448 449 /* 450 * First update the path table sizes for directories. 451 */ 452 if(s_entry->isorec.flags[0] == 2) 453 { 454 if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) 455 { 456 path_table_size += new_reclen + sizeof(struct iso_path_table) - 1; 457 if (new_reclen & 1) path_table_size++; 458 } 459 else 460 { 461 new_reclen = 1; 462 if (this_dir == root && strlen(s_entry->name) == 1) 463 { 464 path_table_size += sizeof(struct iso_path_table); 465 } 466 } 467 } 468 if(path_table_size & 1) path_table_size++; /* For odd lengths we pad */ 469 s_entry->isorec.name_len[0] = new_reclen; 470 471 new_reclen += 472 sizeof(struct iso_directory_record) - 473 sizeof(s_entry->isorec.name); 474 475 if (new_reclen & 1) 476 new_reclen++; 477 478 new_reclen += s_entry->rr_attr_size; 479 480 if (new_reclen & 1) new_reclen++; 481 482 if(new_reclen > 0xff) 483 { 484 fprintf(stderr,"Fatal error - RR overflow for file %s\n", 485 s_entry->name); 486 exit(1); 487 } 488 s_entry->isorec.length[0] = new_reclen; 489 } 490 491 status = sort_directory(&this_dir->contents); 492 if( status > 0 ) 493 { 494 fprintf(stderr, "Unable to sort directory %s\n", 495 this_dir->whole_name); 496 } 497 498 /* 499 * If we are filling out a TRANS.TBL, generate the entries that will 500 * go in the thing. 501 */ 502 if(table) 503 { 504 count = 0; 505 for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){ 506 if(s_entry == table) continue; 507 if(!s_entry->table) continue; 508 if(strcmp(s_entry->name, ".") == 0 || 509 strcmp(s_entry->name, "..") == 0) continue; 510 #ifdef APPLE_HYB 511 /* skip table entry for the resource fork */ 512 if(apple_both && (s_entry->isorec.flags[0] & ASSOC_FLAG)) 513 continue; 514 #endif /* APPLE_HYB */ 515 if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY) continue; 516 /* 517 * Warning: we cannot use the return value of sprintf because 518 * old BSD based sprintf() implementations will return 519 * a pointer to the result instead of a count. 520 */ 521 sprintf(table->table + count, "%c %-34s%s", 522 s_entry->table[0], 523 s_entry->isorec.name, s_entry->table+1); 524 count += strlen(table->table + count); 525 free(s_entry->table); 526 s_entry->table = NULL; 527 } 528 529 if(count != tablesize) 530 { 531 fprintf(stderr,"Translation table size mismatch %d %d\n", 532 count, tablesize); 533 exit(1); 534 } 535 } 536 537 /* 538 * Now go through the directory and figure out how large this one will be. 539 * Do not split a directory entry across a sector boundary 540 */ 541 s_entry = this_dir->contents; 542 this_dir->ce_bytes = 0; 543 while(s_entry) 544 { 545 /* skip if it's hidden */ 546 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) { 547 s_entry = s_entry->next; 548 continue; 549 } 550 551 new_reclen = s_entry->isorec.length[0]; 552 if ((this_dir->size & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE) 553 this_dir->size = (this_dir->size + (SECTOR_SIZE - 1)) & 554 ~(SECTOR_SIZE - 1); 555 this_dir->size += new_reclen; 556 557 /* See if continuation entries were used on disc */ 558 if(use_RockRidge && 559 s_entry->rr_attr_size != s_entry->total_rr_attr_size) 560 { 561 unsigned char * pnt; 562 int len; 563 int nbytes; 564 565 pnt = s_entry->rr_attributes; 566 len = s_entry->total_rr_attr_size; 567 568 /* 569 * We make sure that each continuation entry record is not 570 * split across sectors, but each file could in theory have more 571 * than one CE, so we scan through and figure out what we need. 572 */ 573 while(len > 3) 574 { 575 if(pnt[0] == 'C' && pnt[1] == 'E') 576 { 577 nbytes = get_733((char *) pnt+20); 578 579 if((this_dir->ce_bytes & (SECTOR_SIZE - 1)) + nbytes >= 580 SECTOR_SIZE) this_dir->ce_bytes = 581 ROUND_UP(this_dir->ce_bytes); 582 /* Now store the block in the ce buffer */ 583 this_dir->ce_bytes += nbytes; 584 if(this_dir->ce_bytes & 1) this_dir->ce_bytes++; 585 } 586 len -= pnt[2]; 587 pnt += pnt[2]; 588 } 589 } 590 s_entry = s_entry->next; 591 } 592 return status; 593 } 594 595 static void generate_reloc_directory() 596 { 597 time_t current_time; 598 struct directory_entry *s_entry; 599 600 /* Create an entry for our internal tree */ 601 time (¤t_time); 602 reloc_dir = (struct directory *) 603 e_malloc(sizeof(struct directory)); 604 memset(reloc_dir, 0, sizeof(struct directory)); 605 reloc_dir->parent = root; 606 reloc_dir->next = root->subdir; 607 root->subdir = reloc_dir; 608 reloc_dir->depth = 1; 609 if (hide_rr_moved) { 610 reloc_dir->whole_name = strdup("./.rr_moved"); 611 reloc_dir->de_name = strdup(".rr_moved"); 612 } else { 613 reloc_dir->whole_name = strdup("./rr_moved"); 614 reloc_dir->de_name = strdup("rr_moved"); 615 } 616 reloc_dir->extent = 0; 617 618 619 /* Now create an actual directory entry */ 620 s_entry = (struct directory_entry *) 621 e_malloc(sizeof (struct directory_entry)); 622 memset(s_entry, 0, sizeof(struct directory_entry)); 623 s_entry->next = root->contents; 624 reloc_dir->self = s_entry; 625 626 /* 627 * The rr_moved entry will not appear in the Joliet tree. 628 */ 629 reloc_dir->dir_flags |= INHIBIT_JOLIET_ENTRY; 630 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; 631 632 root->contents = s_entry; 633 root->contents->name = strdup(reloc_dir->de_name); 634 root->contents->filedir = root; 635 root->contents->isorec.flags[0] = 2; 636 root->contents->priority = 32768; 637 iso9660_date(root->contents->isorec.date, current_time); 638 root->contents->inode = UNCACHED_INODE; 639 root->contents->dev = (dev_t) UNCACHED_DEVICE; 640 set_723(root->contents->isorec.volume_sequence_number, volume_sequence_number); 641 iso9660_file_length (reloc_dir->de_name, root->contents, 1); 642 643 if(use_RockRidge){ 644 fstatbuf.st_mode = 0555 | S_IFDIR; 645 fstatbuf.st_nlink = 2; 646 generate_rock_ridge_attributes("", 647 hide_rr_moved ? ".rr_moved" : "rr_moved", 648 s_entry, &fstatbuf, &fstatbuf, 0); 649 }; 650 651 /* Now create the . and .. entries in rr_moved */ 652 /* Now create an actual directory entry */ 653 attach_dot_entries(reloc_dir, &root_statbuf); 654 } 655 656 /* 657 * Function: attach_dot_entries 658 * 659 * Purpose: Create . and .. entries for a new directory. 660 * 661 * Notes: Only used for artificial directories that 662 * we are creating. 663 */ 664 static void FDECL2(attach_dot_entries, struct directory *, dirnode, 665 struct stat *, parent_stat) 666 { 667 struct directory_entry *s_entry; 668 struct directory_entry *orig_contents; 669 int deep_flag = 0; 670 671 init_fstatbuf(); 672 673 orig_contents = dirnode->contents; 674 675 if( (dirnode->dir_flags & DIR_HAS_DOTDOT) == 0 ) 676 { 677 s_entry = (struct directory_entry *) 678 e_malloc(sizeof (struct directory_entry)); 679 memcpy(s_entry, dirnode->self, 680 sizeof(struct directory_entry)); 681 #ifdef APPLE_HYB 682 if (dirnode->self->hfs_ent) { 683 s_entry->hfs_ent = (hfsdirent *) e_malloc(sizeof (hfsdirent)); 684 memcpy(s_entry->hfs_ent, dirnode->self->hfs_ent, 685 sizeof (hfsdirent)); 686 } 687 #endif 688 s_entry->name = strdup(".."); 689 s_entry->whole_name = NULL; 690 s_entry->isorec.name_len[0] = 1; 691 s_entry->isorec.flags[0] = 2; /* Mark as a directory */ 692 iso9660_file_length ("..", s_entry, 1); 693 iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime); 694 s_entry->filedir = dirnode->parent; 695 696 dirnode->contents = s_entry; 697 dirnode->contents->next = orig_contents; 698 orig_contents = s_entry; 699 700 if(use_RockRidge) 701 { 702 if( parent_stat == NULL ) 703 { 704 parent_stat = &fstatbuf; 705 } 706 generate_rock_ridge_attributes("", 707 "..", s_entry, 708 parent_stat, 709 parent_stat, 0); 710 } 711 dirnode->dir_flags |= DIR_HAS_DOTDOT; 712 } 713 714 if( (dirnode->dir_flags & DIR_HAS_DOT) == 0 ) 715 { 716 s_entry = (struct directory_entry *) 717 e_malloc(sizeof (struct directory_entry)); 718 memcpy(s_entry, dirnode->self, 719 sizeof(struct directory_entry)); 720 #ifdef APPLE_HYB 721 if (dirnode->self->hfs_ent) { 722 s_entry->hfs_ent = (hfsdirent *) e_malloc(sizeof (hfsdirent)); 723 memcpy(s_entry->hfs_ent, dirnode->self->hfs_ent, 724 sizeof (hfsdirent)); 725 } 726 #endif 727 s_entry->name = strdup("."); 728 s_entry->whole_name = NULL; 729 s_entry->isorec.name_len[0] = 1; 730 s_entry->isorec.flags[0] = 2; /* Mark as a directory */ 731 iso9660_file_length (".", s_entry, 1); 732 iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime); 733 s_entry->filedir = dirnode; 734 735 dirnode->contents = s_entry; 736 dirnode->contents->next = orig_contents; 737 738 if(use_RockRidge) 739 { 740 fstatbuf.st_mode = 0555 | S_IFDIR; 741 fstatbuf.st_nlink = 2; 742 743 if( dirnode == root ) 744 { 745 deep_flag |= NEED_CE | NEED_SP; /* For extension record */ 746 } 747 748 generate_rock_ridge_attributes("", 749 ".", s_entry, 750 &fstatbuf, &fstatbuf, deep_flag); 751 } 752 753 dirnode->dir_flags |= DIR_HAS_DOT; 754 } 755 756 } 757 758 static void FDECL2(update_nlink, struct directory_entry *, s_entry, int, value) 759 { 760 unsigned char * pnt; 761 int len; 762 763 pnt = s_entry->rr_attributes; 764 len = s_entry->total_rr_attr_size; 765 while(len) 766 { 767 if(pnt[0] == 'P' && pnt[1] == 'X') 768 { 769 set_733((char *) pnt+12, value); 770 break; 771 } 772 len -= pnt[2]; 773 pnt += pnt[2]; 774 } 775 } 776 777 static void FDECL1(increment_nlink, struct directory_entry *, s_entry) 778 { 779 unsigned char * pnt; 780 int len, nlink; 781 782 pnt = s_entry->rr_attributes; 783 len = s_entry->total_rr_attr_size; 784 while(len) 785 { 786 if(pnt[0] == 'P' && pnt[1] == 'X') 787 { 788 nlink = get_733((char *) pnt+12); 789 set_733((char *) pnt+12, nlink+1); 790 break; 791 } 792 len -= pnt[2]; 793 pnt += pnt[2]; 794 } 795 } 796 797 void finish_cl_pl_entries(){ 798 struct directory_entry *s_entry, *s_entry1; 799 struct directory * d_entry; 800 801 /* if the reloc_dir is hidden (empty), then return */ 802 if (reloc_dir->dir_flags & INHIBIT_ISO9660_ENTRY) 803 return; 804 805 s_entry = reloc_dir->contents; 806 s_entry = s_entry->next->next; /* Skip past . and .. */ 807 for(; s_entry; s_entry = s_entry->next){ 808 /* skip if it's hidden */ 809 if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY) { 810 continue; 811 } 812 d_entry = reloc_dir->subdir; 813 while(d_entry){ 814 if(d_entry->self == s_entry) break; 815 d_entry = d_entry->next; 816 }; 817 if(!d_entry){ 818 fprintf(stderr,"Unable to locate directory parent\n"); 819 exit(1); 820 }; 821 822 /* First fix the PL pointer in the directory in the rr_reloc dir */ 823 s_entry1 = d_entry->contents->next; 824 set_733((char *) s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8, 825 s_entry->filedir->extent); 826 827 /* Now fix the CL pointer */ 828 s_entry1 = s_entry->parent_rec; 829 830 set_733((char *) s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8, 831 d_entry->extent); 832 833 s_entry->filedir = reloc_dir; /* Now we can fix this */ 834 } 835 /* Next we need to modify the NLINK terms in the assorted root directory records 836 to account for the presence of the RR_MOVED directory */ 837 838 increment_nlink(root->self); 839 increment_nlink(root->self->next); 840 d_entry = root->subdir; 841 while(d_entry){ 842 increment_nlink(d_entry->contents->next); 843 d_entry = d_entry->next; 844 }; 845 } 846 847 /* 848 * Function: scan_directory_tree 849 * 850 * Purpose: Walk through a directory on the local machine 851 * filter those things we don't want to include 852 * and build our representation of a dir. 853 * 854 * Notes: 855 */ 856 int 857 FDECL3(scan_directory_tree,struct directory *, this_dir, 858 char *, path, 859 struct directory_entry *, de) 860 { 861 DIR * current_dir; 862 char whole_path[1024]; 863 struct dirent * d_entry; 864 struct directory * parent; 865 int dflag; 866 char * old_path; 867 868 if (verbose > 1) 869 { 870 fprintf(stderr, "Scanning %s\n", path); 871 } 872 873 current_dir = opendir(path); 874 d_entry = NULL; 875 876 /* Apparently NFS sometimes allows you to open the directory, but 877 then refuses to allow you to read the contents. Allow for this */ 878 879 old_path = path; 880 881 if(current_dir) d_entry = readdir(current_dir); 882 883 if(!current_dir || !d_entry) 884 { 885 fprintf(stderr,"Unable to open directory %s\n", path); 886 de->isorec.flags[0] &= ~2; /* Mark as not a directory */ 887 if(current_dir) closedir(current_dir); 888 return 0; 889 } 890 891 parent = de->filedir; 892 /* Set up the struct for the current directory, and insert it into the 893 tree */ 894 895 #ifdef VMS 896 vms_path_fixup(path); 897 #endif 898 899 /* 900 * if entry for this sub-directory is hidden, then hide this directory 901 */ 902 if (de->de_flags & INHIBIT_ISO9660_ENTRY) 903 this_dir->dir_flags |= INHIBIT_ISO9660_ENTRY; 904 905 if (de->de_flags & INHIBIT_JOLIET_ENTRY) 906 this_dir->dir_flags |= INHIBIT_JOLIET_ENTRY; 907 908 /* 909 * Now we scan the directory itself, and look at what is inside of it. 910 */ 911 dflag = 0; 912 while(1==1){ 913 914 /* The first time through, skip this, since we already asked for 915 the first entry when we opened the directory. */ 916 if(dflag) d_entry = readdir(current_dir); 917 dflag++; 918 919 if(!d_entry) break; 920 921 /* OK, got a valid entry */ 922 923 /* If we do not want all files, then pitch the backups. */ 924 if(!all_files){ 925 if( strchr(d_entry->d_name,'~') 926 || strchr(d_entry->d_name,'#')) 927 { 928 if( verbose > 0 ) 929 { 930 fprintf(stderr, "Ignoring file %s\n", d_entry->d_name); 931 } 932 continue; 933 } 934 } 935 936 #ifdef APPLE_HYB 937 if (apple_both) { 938 /* exclude certain HFS type files/directories for the time being */ 939 if (hfs_exclude(d_entry->d_name)) 940 continue; 941 } 942 #endif /* APPLE_HYB */ 943 944 if(strlen(path)+strlen(d_entry->d_name) + 2 > sizeof(whole_path)){ 945 fprintf(stderr, "Overflow of stat buffer\n"); 946 exit(1); 947 }; 948 949 /* Generate the complete ASCII path for this file */ 950 strcpy(whole_path, path); 951 #ifndef VMS 952 if(whole_path[strlen(whole_path)-1] != '/') 953 strcat(whole_path, "/"); 954 #endif 955 strcat(whole_path, d_entry->d_name); 956 957 /** Should we exclude this file ? */ 958 if (matches(d_entry->d_name) || matches(whole_path)) { 959 if (verbose > 1) { 960 fprintf(stderr, "Excluded by match: %s\n", whole_path); 961 } 962 continue; 963 } 964 965 if( generate_tables 966 #ifdef APPLE_HYB 967 && strcmp(d_entry->d_name, trans_tbl) == 0 ) 968 #else 969 && strcmp(d_entry->d_name, "TRANS.TBL") == 0 ) 970 #endif /* APPLE_HYB */ 971 { 972 /* 973 * Ignore this entry. We are going to be generating new 974 * versions of these files, and we need to ignore any 975 * originals that we might have found. 976 */ 977 if (verbose > 1) 978 { 979 fprintf(stderr, "Excluded: %s\n",whole_path); 980 } 981 continue; 982 } 983 984 /* 985 * If we already have a '.' or a '..' entry, then don't 986 * insert new ones. 987 */ 988 if( strcmp(d_entry->d_name, ".") == 0 989 && this_dir->dir_flags & DIR_HAS_DOT ) 990 { 991 continue; 992 } 993 994 if( strcmp(d_entry->d_name, "..") == 0 995 && this_dir->dir_flags & DIR_HAS_DOTDOT ) 996 { 997 continue; 998 } 999 1000 #if 0 1001 if (verbose > 1) fprintf(stderr, "%s\n",whole_path); 1002 #endif 1003 /* 1004 * This actually adds the entry to the directory in question. 1005 */ 1006 #ifdef APPLE_HYB 1007 insert_file_entry(this_dir, whole_path, d_entry->d_name, 0); 1008 #else 1009 insert_file_entry(this_dir, whole_path, d_entry->d_name); 1010 #endif /* APPLE_HYB */ 1011 } 1012 closedir(current_dir); 1013 1014 #ifdef APPLE_HYB 1015 /* if we cached the HFS info stuff for this directory, then delete it */ 1016 if (this_dir->hfs_info) { 1017 del_hfs_info(this_dir->hfs_info); 1018 this_dir->hfs_info = 0; 1019 } 1020 #endif /* APPLE_HYB */ 1021 1022 return 1; 1023 } 1024 1025 1026 /* 1027 * Function: insert_file_entry 1028 * 1029 * Purpose: Insert one entry into our directory node. 1030 * 1031 * Note: 1032 * This function inserts a single entry into the directory. It 1033 * is assumed that all filtering and decision making regarding what 1034 * we want to include has already been made, so the purpose of this 1035 * is to insert one entry (file, link, dir, etc), into this directory. 1036 * Note that if the entry is a dir (or if we are following links, 1037 * and the thing it points to is a dir), then we will scan those 1038 * trees before we return. 1039 */ 1040 #ifdef APPLE_HYB 1041 int 1042 FDECL4(insert_file_entry,struct directory *, this_dir, 1043 char *, whole_path, 1044 char *, short_name, 1045 int, have_rsrc) 1046 #else 1047 int 1048 FDECL3(insert_file_entry,struct directory *, this_dir, 1049 char *, whole_path, 1050 char *, short_name) 1051 #endif /* APPLE_HYB */ 1052 { 1053 struct stat statbuf, lstatbuf; 1054 struct directory_entry * s_entry, *s_entry1; 1055 int lstatus; 1056 int status; 1057 int deep_flag; 1058 #ifdef APPLE_HYB 1059 int x_hfs = 0; 1060 int htype = 0; 1061 #endif /* APPLE_HYB */ 1062 1063 status = stat_filter(whole_path, &statbuf); 1064 1065 lstatus = lstat_filter(whole_path, &lstatbuf); 1066 1067 if( (status == -1) && (lstatus == -1) ) 1068 { 1069 /* 1070 * This means that the file doesn't exist, or isn't accessible. 1071 * Sometimes this is because of NFS permissions problems. 1072 */ 1073 fprintf(stderr, "Non-existant or inaccessible: %s\n",whole_path); 1074 return 0; 1075 } 1076 1077 if(this_dir == root && strcmp(short_name, ".") == 0) 1078 root_statbuf = statbuf; /* Save this for later on */ 1079 1080 /* We do this to make sure that the root entries are consistent */ 1081 if(this_dir == root && strcmp(short_name, "..") == 0) 1082 { 1083 statbuf = root_statbuf; 1084 lstatbuf = root_statbuf; 1085 } 1086 1087 if(S_ISLNK(lstatbuf.st_mode)) 1088 { 1089 1090 /* Here we decide how to handle the symbolic links. Here 1091 we handle the general case - if we are not following 1092 links or there is an error, then we must change 1093 something. If RR is in use, it is easy, we let RR 1094 describe the file. If not, then we punt the file. */ 1095 1096 if((status || !follow_links)) 1097 { 1098 if(use_RockRidge) 1099 { 1100 status = 0; 1101 statbuf.st_size = 0; 1102 STAT_INODE(statbuf) = UNCACHED_INODE; 1103 statbuf.st_dev = (dev_t) UNCACHED_DEVICE; 1104 statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG; 1105 } else { 1106 if(follow_links) 1107 { 1108 fprintf(stderr, 1109 "Unable to stat file %s - ignoring and continuing.\n", 1110 whole_path); 1111 } 1112 else 1113 { 1114 fprintf(stderr, 1115 "Symlink %s ignored - continuing.\n", 1116 whole_path); 1117 return 0; /* Non Rock Ridge discs - ignore all symlinks */ 1118 } 1119 } 1120 } 1121 1122 /* Here we handle a different kind of case. Here we have 1123 a symlink, but we want to follow symlinks. If we run 1124 across a directory loop, then we need to pretend that 1125 we are not following symlinks for this file. If this 1126 is the first time we have seen this, then make this 1127 seem as if there was no symlink there in the first 1128 place */ 1129 1130 if( follow_links 1131 && S_ISDIR(statbuf.st_mode) ) 1132 { 1133 if( strcmp(short_name, ".") 1134 && strcmp(short_name, "..") ) 1135 { 1136 if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) 1137 { 1138 if(!use_RockRidge) 1139 { 1140 fprintf(stderr, "Already cached directory seen (%s)\n", 1141 whole_path); 1142 return 0; 1143 } 1144 statbuf.st_size = 0; 1145 STAT_INODE(statbuf) = UNCACHED_INODE; 1146 statbuf.st_dev = (dev_t) UNCACHED_DEVICE; 1147 statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG; 1148 } 1149 else 1150 { 1151 lstatbuf = statbuf; 1152 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); 1153 } 1154 } 1155 } 1156 1157 /* 1158 * For non-directories, we just copy the stat information over 1159 * so we correctly include this file. 1160 */ 1161 if( follow_links 1162 && !S_ISDIR(statbuf.st_mode) ) 1163 { 1164 lstatbuf = statbuf; 1165 } 1166 } 1167 1168 /* 1169 * Add directories to the cache so that we don't waste space even 1170 * if we are supposed to be following symlinks. 1171 */ 1172 if( follow_links 1173 && strcmp(short_name, ".") 1174 && strcmp(short_name, "..") 1175 && S_ISDIR(statbuf.st_mode) ) 1176 { 1177 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); 1178 } 1179 #ifdef VMS 1180 if(!S_ISDIR(lstatbuf.st_mode) && (statbuf.st_fab_rfm != FAB$C_FIX && 1181 statbuf.st_fab_rfm != FAB$C_STMLF)) { 1182 fprintf(stderr,"Warning - file %s has an unsupported VMS record" 1183 " format (%d)\n", 1184 whole_path, statbuf.st_fab_rfm); 1185 } 1186 #endif 1187 1188 if(S_ISREG(lstatbuf.st_mode) && (status = access(whole_path, R_OK))) 1189 { 1190 fprintf(stderr, "File %s is not readable (errno = %d) - ignoring\n", 1191 whole_path, errno); 1192 return 0; 1193 } 1194 1195 /* Add this so that we can detect directory loops with hard links. 1196 If we are set up to follow symlinks, then we skip this checking. */ 1197 if( !follow_links 1198 && S_ISDIR(lstatbuf.st_mode) 1199 && strcmp(short_name, ".") 1200 && strcmp(short_name, "..") ) 1201 { 1202 if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) { 1203 #ifdef APPLE_HYB 1204 /* NON-HFS change - print just a warning *if* this ever happens */ 1205 fprintf(stderr,"Warning: Directory loop (%s)\n", whole_path); 1206 #else 1207 fprintf(stderr,"Directory loop - fatal goof (%s %lx %llu).\n", 1208 whole_path, (unsigned long) statbuf.st_dev, 1209 (unsigned long long) STAT_INODE(statbuf)); 1210 exit(1); 1211 #endif 1212 } 1213 add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); 1214 } 1215 1216 if (!S_ISCHR(lstatbuf.st_mode) && !S_ISBLK(lstatbuf.st_mode) && 1217 !S_ISFIFO(lstatbuf.st_mode) && !S_ISSOCK(lstatbuf.st_mode) 1218 && !S_ISLNK(lstatbuf.st_mode) && !S_ISREG(lstatbuf.st_mode) && 1219 !S_ISDIR(lstatbuf.st_mode)) { 1220 fprintf(stderr,"Unknown file type %s - ignoring and continuing.\n", 1221 whole_path); 1222 return 0; 1223 } 1224 1225 /* Who knows what trash this is - ignore and continue */ 1226 1227 if(status) 1228 { 1229 fprintf(stderr, 1230 "Unable to stat file %s - ignoring and continuing.\n", 1231 whole_path); 1232 return 0; 1233 } 1234 1235 /* 1236 * Check to see if we have already seen this directory node. 1237 * If so, then we don't create a new entry for it, but we do want 1238 * to recurse beneath it and add any new files we do find. 1239 */ 1240 if (S_ISDIR(statbuf.st_mode)) 1241 { 1242 int dflag; 1243 1244 for( s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) 1245 { 1246 if( strcmp(s_entry->name, short_name) == 0 ) 1247 { 1248 break; 1249 } 1250 } 1251 if ( s_entry != NULL 1252 && strcmp(short_name,".") 1253 && strcmp(short_name,"..")) 1254 { 1255 struct directory * child; 1256 1257 if ( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0) 1258 { 1259 for( s_entry = reloc_dir->contents; s_entry; s_entry = s_entry->next) 1260 { 1261 if( strcmp(s_entry->name, short_name) == 0 ) 1262 { 1263 break; 1264 } 1265 } 1266 child = find_or_create_directory(reloc_dir, whole_path, 1267 s_entry, 1); 1268 } 1269 else 1270 { 1271 child = find_or_create_directory(this_dir, whole_path, 1272 s_entry, 1); 1273 /* If unable to scan directory, mark this as a non-directory */ 1274 } 1275 dflag = scan_directory_tree(child, whole_path, s_entry); 1276 if(!dflag) 1277 { 1278 lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG; 1279 } 1280 return 0; 1281 } 1282 } 1283 #ifdef APPLE_HYB 1284 /* Should we exclude this HFS file ? - only works with -hfs */ 1285 if (!have_rsrc && apple_hyb && strcmp(short_name,".") && strcmp(short_name,"..")) { 1286 x_hfs = hfs_matches(short_name) || hfs_matches(whole_path); 1287 if (x_hfs) { 1288 if (verbose > 1) { 1289 fprintf(stderr, "Hidden from HFS tree: %s\n", whole_path); 1290 } 1291 } 1292 } 1293 1294 /* check we are a file, using Apple extensions and have a .resource part 1295 and not excluded */ 1296 if (S_ISREG(lstatbuf.st_mode) && !have_rsrc && apple_both && !x_hfs) { 1297 char rsrc_path[1024]; /* rsrc fork filename */ 1298 1299 /* construct the resource full path */ 1300 htype = get_hfs_rname(whole_path, short_name, rsrc_path); 1301 /* check we can read the resouce fork */ 1302 if (htype) { 1303 struct stat rstatbuf, rlstatbuf; 1304 1305 /* some further checks on the file */ 1306 status = stat_filter(rsrc_path, &rstatbuf); 1307 1308 lstatus = lstat_filter(rsrc_path, &rlstatbuf); 1309 1310 if(!status && !lstatus && S_ISREG(rstatbuf.st_mode) && rstatbuf.st_size > 0) { 1311 /* have a resource file - insert it into the current directory 1312 but flag that we have a resource fork */ 1313 insert_file_entry(this_dir, rsrc_path, short_name, htype); 1314 } 1315 } 1316 } 1317 #endif /* APPLE_HYB */ 1318 1319 s_entry = (struct directory_entry *) 1320 e_malloc(sizeof (struct directory_entry)); 1321 /* memset the whole struct, not just the isorec.extent part JCP */ 1322 memset(s_entry, 0, sizeof (struct directory_entry)); 1323 s_entry->next = this_dir->contents; 1324 /*memset(s_entry->isorec.extent, 0, 8); */ 1325 this_dir->contents = s_entry; 1326 deep_flag = 0; 1327 s_entry->table = NULL; 1328 1329 s_entry->name = strdup(short_name); 1330 s_entry->whole_name = strdup (whole_path); 1331 1332 s_entry->de_flags = 0; 1333 1334 /* 1335 * If the current directory is hidden, then hide all it's members 1336 * otherwise check if this entry needs to be hidden as well */ 1337 if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY) { 1338 s_entry->de_flags |= INHIBIT_ISO9660_ENTRY; 1339 } 1340 else if (strcmp(short_name,".") && strcmp(short_name,"..")) { 1341 if (i_matches(short_name) || i_matches(whole_path)) { 1342 if (verbose > 1) { 1343 fprintf(stderr, "Hidden from ISO9660 tree: %s\n", whole_path); 1344 } 1345 s_entry->de_flags |= INHIBIT_ISO9660_ENTRY; 1346 } 1347 } 1348 1349 if (this_dir != reloc_dir && this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) { 1350 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; 1351 } 1352 else if (strcmp(short_name,".") && strcmp(short_name,"..")) { 1353 if (j_matches(short_name) || j_matches(whole_path)) { 1354 if (verbose > 1) { 1355 fprintf(stderr, "Hidden from Joliet tree: %s\n", whole_path); 1356 } 1357 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; 1358 } 1359 } 1360 1361 s_entry->filedir = this_dir; 1362 s_entry->isorec.flags[0] = 0; 1363 s_entry->isorec.ext_attr_length[0] = 0; 1364 iso9660_date(s_entry->isorec.date, statbuf.st_mtime); 1365 s_entry->isorec.file_unit_size[0] = 0; 1366 s_entry->isorec.interleave[0] = 0; 1367 1368 #ifdef APPLE_HYB 1369 if (apple_both && !x_hfs) { 1370 s_entry->hfs_ent = NULL; 1371 s_entry->assoc = NULL; 1372 s_entry->hfs_off = 0; 1373 s_entry->hfs_type = htype; 1374 if (have_rsrc) { 1375 s_entry->isorec.flags[0] = ASSOC_FLAG; /* associated (rsrc) file */ 1376 /* set the type of HFS file */ 1377 s_entry->hfs_type = have_rsrc; 1378 /* don't want the rsrc file to be included in any Joliet tree */ 1379 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; 1380 } 1381 else if (s_entry->next) { 1382 /* if previous entry is an associated file, then "link" it 1383 to this file i.e. we have a data/resource pair */ 1384 if (s_entry->next->isorec.flags[0] & ASSOC_FLAG) { 1385 s_entry->assoc = s_entry->next; 1386 /* share the same HFS parameters */ 1387 s_entry->hfs_ent = s_entry->next->hfs_ent; 1388 s_entry->hfs_type = s_entry->next->hfs_type; 1389 } 1390 } 1391 /* allocate HFS entry if required */ 1392 if (apple_both && strcmp(short_name, ".") && strcmp(short_name, "..")) { 1393 if (!s_entry->hfs_ent) { 1394 hfsdirent *hfs_ent; 1395 hfs_ent = (hfsdirent *)e_malloc(sizeof(hfsdirent)); 1396 1397 /* fill in the defaults */ 1398 hfs_ent->flags = hfs_ent->fdflags = 0; 1399 hfs_ent->crdate = lstatbuf.st_ctime; 1400 hfs_ent->mddate = lstatbuf.st_mtime; 1401 hfs_ent->dsize = hfs_ent->rsize = 0; 1402 s_entry->hfs_ent = hfs_ent; 1403 } 1404 if (have_rsrc) 1405 /* set rsrc size */ 1406 s_entry->hfs_ent->rsize = lstatbuf.st_size; 1407 else 1408 /* set data size */ 1409 s_entry->hfs_ent->dsize = lstatbuf.st_size; 1410 } 1411 } 1412 #endif /* APPLE_HYB */ 1413 1414 if( strcmp(short_name, ".") == 0) 1415 { 1416 this_dir->dir_flags |= DIR_HAS_DOT; 1417 } 1418 1419 if( strcmp(short_name, "..") == 0) 1420 { 1421 this_dir->dir_flags |= DIR_HAS_DOTDOT; 1422 } 1423 1424 if( this_dir->parent 1425 && this_dir->parent == reloc_dir 1426 && strcmp(short_name, "..") == 0) 1427 { 1428 s_entry->inode = UNCACHED_INODE; 1429 s_entry->dev = (dev_t) UNCACHED_DEVICE; 1430 deep_flag = NEED_PL; 1431 } 1432 else 1433 #ifdef APPLE_HYB 1434 if (have_rsrc) { 1435 /* don't want rsrc files to be cached */ 1436 s_entry->inode = UNCACHED_INODE; 1437 s_entry->dev = (dev_t) UNCACHED_DEVICE; 1438 } 1439 else 1440 #endif /* APPLE_HYB */ 1441 { 1442 s_entry->inode = STAT_INODE(statbuf); 1443 s_entry->dev = statbuf.st_dev; 1444 } 1445 set_723(s_entry->isorec.volume_sequence_number, volume_sequence_number); 1446 iso9660_file_length(short_name, s_entry, S_ISDIR(statbuf.st_mode)); 1447 s_entry->rr_attr_size = 0; 1448 s_entry->total_rr_attr_size = 0; 1449 s_entry->rr_attributes = NULL; 1450 1451 /* Directories are assigned sizes later on */ 1452 if (!S_ISDIR(statbuf.st_mode)) 1453 { 1454 if (S_ISCHR(lstatbuf.st_mode) || S_ISBLK(lstatbuf.st_mode) || 1455 S_ISFIFO(lstatbuf.st_mode) || S_ISSOCK(lstatbuf.st_mode) 1456 || S_ISLNK(lstatbuf.st_mode)) 1457 { 1458 s_entry->size = 0; 1459 statbuf.st_size = 0; 1460 } 1461 else 1462 { 1463 s_entry->size = statbuf.st_size; 1464 } 1465 1466 set_733((char *) s_entry->isorec.size, statbuf.st_size); 1467 } 1468 else 1469 { 1470 s_entry->isorec.flags[0] = 2; 1471 } 1472 #ifdef APPLE_HYB 1473 /* if the directory is HFS excluded, then we don't have an hfs_ent */ 1474 if (apple_both && s_entry->hfs_ent && s_entry->isorec.flags[0] & 2) { 1475 /* get the Mac directory name */ 1476 get_hfs_dir(whole_path, short_name, s_entry); 1477 1478 /* if required, set ISO directory name from HFS name */ 1479 if (mac_name) 1480 iso9660_file_length(s_entry->hfs_ent->name, s_entry, 1); 1481 } 1482 #endif /* APPLE_HYB */ 1483 1484 if (strcmp(short_name,".") && strcmp(short_name,"..") && 1485 S_ISDIR(statbuf.st_mode) && this_dir->depth > RR_relocation_depth) 1486 { 1487 struct directory * child; 1488 1489 if(!reloc_dir) generate_reloc_directory(); 1490 1491 /* 1492 * Replicate the entry for this directory. The old one will stay where it 1493 * is, and it will be neutered so that it no longer looks like a directory. 1494 * The new one will look like a directory, and it will be put in the reloc_dir. 1495 */ 1496 s_entry1 = (struct directory_entry *) 1497 e_malloc(sizeof (struct directory_entry)); 1498 memcpy(s_entry1, s_entry, sizeof(struct directory_entry)); 1499 s_entry1->table = NULL; 1500 s_entry1->name = strdup(this_dir->contents->name); 1501 s_entry1->whole_name = strdup(this_dir->contents->whole_name); 1502 s_entry1->next = reloc_dir->contents; 1503 reloc_dir->contents = s_entry1; 1504 s_entry1->priority = 32768; 1505 s_entry1->parent_rec = this_dir->contents; 1506 1507 deep_flag = NEED_RE; 1508 1509 if(use_RockRidge) 1510 { 1511 generate_rock_ridge_attributes(whole_path, 1512 short_name, s_entry1, 1513 &statbuf, &lstatbuf, deep_flag); 1514 } 1515 1516 deep_flag = 0; 1517 1518 /* We need to set this temporarily so that the parent to this 1519 is correctly determined. */ 1520 s_entry1->filedir = reloc_dir; 1521 child = find_or_create_directory(reloc_dir, whole_path, 1522 s_entry1, 0); 1523 scan_directory_tree(child, whole_path, s_entry1); 1524 s_entry1->filedir = this_dir; 1525 1526 statbuf.st_size = 0; 1527 statbuf.st_mode &= 0777; 1528 set_733((char *) s_entry->isorec.size, 0); 1529 s_entry->size = 0; 1530 s_entry->isorec.flags[0] = 0; 1531 s_entry->inode = UNCACHED_INODE; 1532 s_entry->de_flags |= RELOCATED_DIRECTORY; 1533 deep_flag = NEED_CL; 1534 } 1535 1536 if(generate_tables 1537 && strcmp(s_entry->name, ".") 1538 && strcmp(s_entry->name, "..")) 1539 { 1540 char buffer[2048]; 1541 int nchar; 1542 switch(lstatbuf.st_mode & S_IFMT) 1543 { 1544 case S_IFDIR: 1545 snprintf(buffer, sizeof buffer, "D\t%s\n", 1546 s_entry->name); 1547 break; 1548 #ifdef S_IFBLK 1549 /* extra for WIN32 - if it doesn't have the major/minor defined, then 1550 S_IFBLK and S_IFCHR type files are unlikely to exist anyway ... 1551 code similar to that in rock.c */ 1552 1553 /* for some reason, MAJOR_IN_SYSMACROS isn't defined on a SunOS when 1554 it should be, so see if major() is defined instead */ 1555 /* 1556 #if !(defined(MAJOR_IN_SYSMACROS) || defined(MAJOR_IN_MKDEV)) 1557 */ 1558 #ifndef major 1559 #define major(dev) (sizeof(dev_t) <= 2 ? ((dev) >> 8) : \ 1560 (sizeof(dev_t) <= 4 ? (((dev) >> 8) >> 8) : \ 1561 (((dev) >> 16) >> 16))) 1562 #define minor(dev) (sizeof(dev_t) <= 2 ? (dev) & 0xff : \ 1563 (sizeof(dev_t) <= 4 ? (dev) & 0xffff : \ 1564 (dev) & 0xffffffff)) 1565 #endif 1566 case S_IFBLK: 1567 snprintf(buffer, sizeof buffer, "B\t%s\t%lu %lu\n", 1568 s_entry->name, 1569 (unsigned long) major(statbuf.st_rdev), 1570 (unsigned long) minor(statbuf.st_rdev)); 1571 break; 1572 #endif 1573 #ifdef S_IFIFO 1574 case S_IFIFO: 1575 snprintf(buffer, sizeof buffer, "P\t%s\n", 1576 s_entry->name); 1577 break; 1578 #endif 1579 #ifdef S_IFCHR 1580 case S_IFCHR: 1581 snprintf(buffer, sizeof buffer, "C\t%s\t%lu %lu\n", 1582 s_entry->name, 1583 (unsigned long) major(statbuf.st_rdev), 1584 (unsigned long) minor(statbuf.st_rdev)); 1585 break; 1586 #endif 1587 #ifdef S_IFLNK 1588 case S_IFLNK: 1589 nchar = readlink(whole_path, 1590 (char *)symlink_buff, 1591 sizeof(symlink_buff)-1); 1592 symlink_buff[nchar < 0 ? 0 : nchar] = 0; 1593 snprintf(buffer, sizeof buffer, "L\t%s\t%s\n", 1594 s_entry->name, symlink_buff); 1595 break; 1596 #endif 1597 #ifdef S_IFSOCK 1598 case S_IFSOCK: 1599 snprintf(buffer, sizeof buffer, "S\t%s\n", 1600 s_entry->name); 1601 break; 1602 #endif 1603 case S_IFREG: 1604 default: 1605 snprintf(buffer, sizeof buffer, "F\t%s\n", 1606 s_entry->name); 1607 break; 1608 }; 1609 s_entry->table = strdup(buffer); 1610 } 1611 1612 if(S_ISDIR(statbuf.st_mode)) 1613 { 1614 int dflag; 1615 if (strcmp(short_name,".") && strcmp(short_name,"..")) 1616 { 1617 struct directory * child; 1618 1619 child = find_or_create_directory(this_dir, whole_path, 1620 s_entry, 1); 1621 dflag = scan_directory_tree(child, whole_path, s_entry); 1622 1623 if(!dflag) 1624 { 1625 lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG; 1626 if( child->contents == NULL ) 1627 { 1628 delete_directory(this_dir, child); 1629 } 1630 } 1631 } 1632 /* If unable to scan directory, mark this as a non-directory */ 1633 } 1634 1635 if(use_RockRidge && this_dir == root && strcmp(s_entry->name, ".") == 0) 1636 { 1637 deep_flag |= NEED_CE | NEED_SP; /* For extension record */ 1638 } 1639 1640 /* Now figure out how much room this file will take in the 1641 directory */ 1642 1643 #ifdef APPLE_HYB 1644 /* if the file is HFS excluded, then we don't have an hfs_ent */ 1645 if (apple_both && !have_rsrc && s_entry->hfs_ent) { 1646 if (S_ISREG(lstatbuf.st_mode)) { /* it's a regular file */ 1647 1648 /* fill in the rest of the HFS entry */ 1649 get_hfs_info(whole_path, short_name, s_entry); 1650 1651 /* if required, set ISO directory name from HFS name */ 1652 if (mac_name) 1653 iso9660_file_length(s_entry->hfs_ent->name, s_entry, 0); 1654 1655 /* print details about the HFS file */ 1656 if (verbose > 2) 1657 print_hfs_info(s_entry); 1658 1659 /* copy the new ISO9660 name to the rsrc fork - if it exists */ 1660 if (s_entry->assoc) 1661 strcpy(s_entry->assoc->isorec.name, s_entry->isorec.name); 1662 1663 /* we can't handle hard links in the hybrid case, so we "uncache" 1664 the file. The downside to this is that hard linked files 1665 are added to the output image more than once (we've already 1666 done this for rsrc files) */ 1667 if (apple_hyb) { 1668 s_entry->inode = UNCACHED_INODE; 1669 s_entry->dev = (dev_t) UNCACHED_DEVICE; 1670 } 1671 } 1672 else if (!(s_entry->isorec.flags[0] & 2)) { /* not a directory .. */ 1673 1674 /* no mac equivalent, so ignore - have to be careful here, the 1675 hfs_ent may be also be for a relocated directory */ 1676 if (s_entry->hfs_ent && !(s_entry->de_flags & RELOCATED_DIRECTORY)) 1677 free(s_entry->hfs_ent); 1678 s_entry->hfs_ent = NULL; 1679 } 1680 1681 /* if the rsrc size is zero, then we don't need the entry, so we 1682 might as well delete it - this will only happen if we didn't 1683 know the rsrc size from the rsrc file size */ 1684 if(s_entry->assoc && s_entry->assoc->size == 0) 1685 delete_rsrc_ent(s_entry); 1686 } 1687 1688 if(apple_ext && s_entry->assoc) { 1689 /* need Apple extensions for the resource fork as well */ 1690 generate_rock_ridge_attributes(whole_path, 1691 short_name, s_entry->assoc, 1692 &statbuf, &lstatbuf, deep_flag); 1693 } 1694 /* leave out resource fork for the time being */ 1695 if (use_RockRidge && !have_rsrc) { 1696 #else 1697 if(use_RockRidge) 1698 { 1699 #endif /* APPLE_HYB */ 1700 generate_rock_ridge_attributes(whole_path, 1701 short_name, s_entry, 1702 &statbuf, &lstatbuf, deep_flag); 1703 1704 } 1705 1706 return 1; 1707 } 1708 1709 1710 void FDECL2(generate_iso9660_directories, struct directory *, node, FILE*, outfile){ 1711 struct directory * dpnt; 1712 1713 dpnt = node; 1714 1715 while (dpnt){ 1716 if( dpnt->extent > session_start ) 1717 { 1718 generate_one_directory(dpnt, outfile); 1719 } 1720 if(dpnt->subdir) generate_iso9660_directories(dpnt->subdir, outfile); 1721 dpnt = dpnt->next; 1722 } 1723 } 1724 1725 /* 1726 * Function: find_or_create_directory 1727 * 1728 * Purpose: Locate a directory entry in the tree, create if needed. 1729 * 1730 * Arguments: 1731 */ 1732 struct directory * FDECL4(find_or_create_directory, struct directory *, parent, 1733 const char *, path, 1734 struct directory_entry *, de, int, flag) 1735 { 1736 struct directory * dpnt; 1737 struct directory_entry * orig_de; 1738 struct directory * next_brother; 1739 const char * cpnt; 1740 const char * pnt; 1741 1742 orig_de = de; 1743 1744 pnt = strrchr(path, PATH_SEPARATOR); 1745 if( pnt == NULL ) 1746 { 1747 pnt = path; 1748 } 1749 else 1750 { 1751 pnt++; 1752 } 1753 1754 if( parent != NULL ) 1755 { 1756 dpnt = parent->subdir; 1757 1758 while (dpnt) 1759 { 1760 /* 1761 * Weird hack time - if there are two directories by the 1762 * same name in the reloc_dir, they are not treated as the 1763 * same thing unless the entire path matches completely. 1764 */ 1765 if( flag && strcmp(dpnt->de_name, pnt) == 0 ) 1766 { 1767 return dpnt; 1768 } 1769 dpnt = dpnt->next; 1770 } 1771 } 1772 1773 /* 1774 * We don't know if we have a valid directory entry for this one 1775 * yet. If not, we need to create one. 1776 */ 1777 if( de == NULL ) 1778 { 1779 de = (struct directory_entry *) 1780 e_malloc(sizeof (struct directory_entry)); 1781 memset(de, 0, sizeof(struct directory_entry)); 1782 de->next = parent->contents; 1783 parent->contents = de; 1784 de->name = strdup(pnt); 1785 de->filedir = parent; 1786 de->isorec.flags[0] = 2; 1787 de->priority = 32768; 1788 de->inode = UNCACHED_INODE; 1789 de->dev = (dev_t) UNCACHED_DEVICE; 1790 set_723(de->isorec.volume_sequence_number, volume_sequence_number); 1791 iso9660_file_length (pnt, de, 1); 1792 1793 init_fstatbuf(); 1794 /* 1795 * It doesn't exist for real, so we cannot add any Rock Ridge. 1796 */ 1797 if(use_RockRidge) 1798 { 1799 fstatbuf.st_mode = 0555 | S_IFDIR; 1800 fstatbuf.st_nlink = 2; 1801 generate_rock_ridge_attributes("", 1802 (char *) pnt, de, 1803 &fstatbuf, 1804 &fstatbuf, 0); 1805 } 1806 iso9660_date(de->isorec.date, fstatbuf.st_mtime); 1807 #ifdef APPLE_HYB 1808 if (apple_both) { 1809 /* give the directory an HFS entry */ 1810 hfsdirent *hfs_ent; 1811 hfs_ent = (hfsdirent *)e_malloc(sizeof(hfsdirent)); 1812 1813 /* fill in the defaults */ 1814 hfs_ent->flags = hfs_ent->fdflags = 0; 1815 hfs_ent->crdate = fstatbuf.st_ctime; 1816 hfs_ent->mddate = fstatbuf.st_mtime; 1817 hfs_ent->dsize = hfs_ent->rsize = 0; 1818 1819 de->hfs_ent = hfs_ent; 1820 1821 /* get the Mac directory name */ 1822 get_hfs_dir(path, pnt, de); 1823 } 1824 #endif /* APPLE_HYB */ 1825 } 1826 1827 /* 1828 * If we don't have a directory for this one yet, then allocate it 1829 * now, and patch it into the tree in the appropriate place. 1830 */ 1831 dpnt = (struct directory *) e_malloc(sizeof(struct directory)); 1832 memset(dpnt, 0, sizeof(struct directory)); 1833 dpnt->next = NULL; 1834 dpnt->subdir = NULL; 1835 dpnt->self = de; 1836 dpnt->contents = NULL; 1837 dpnt->whole_name = strdup(path); 1838 cpnt = strrchr(path, PATH_SEPARATOR); 1839 if(cpnt) 1840 cpnt++; 1841 else 1842 cpnt = path; 1843 dpnt->de_name = strdup(cpnt); 1844 dpnt->size = 0; 1845 dpnt->extent = 0; 1846 dpnt->jextent = 0; 1847 dpnt->jsize = 0; 1848 #ifdef APPLE_HYB 1849 dpnt->hfs_ent = de->hfs_ent; 1850 #endif /*APPLE_HYB */ 1851 1852 if( orig_de == NULL ) 1853 { 1854 struct stat xstatbuf; 1855 int sts; 1856 1857 /* 1858 * Now add a . and .. entry in the directory itself. 1859 * This is a little tricky - if the real directory 1860 * exists, we need to stat it first. Otherwise, we 1861 * use the fictitious fstatbuf which points to the time 1862 * at which mkisofs was started. 1863 */ 1864 sts = stat_filter(parent->whole_name, &xstatbuf); 1865 if( sts == 0 ) 1866 { 1867 attach_dot_entries(dpnt, &xstatbuf); 1868 } 1869 else 1870 { 1871 attach_dot_entries(dpnt, &fstatbuf); 1872 } 1873 } 1874 1875 if(!parent || parent == root) 1876 { 1877 if (!root) 1878 { 1879 root = dpnt; /* First time through for root directory only */ 1880 root->depth = 0; 1881 root->parent = root; 1882 } else { 1883 dpnt->depth = 1; 1884 if(!root->subdir) 1885 { 1886 root->subdir = dpnt; 1887 } 1888 else 1889 { 1890 next_brother = root->subdir; 1891 while(next_brother->next) next_brother = next_brother->next; 1892 next_brother->next = dpnt; 1893 } 1894 dpnt->parent = parent; 1895 } 1896 } 1897 else 1898 { 1899 /* Come through here for normal traversal of tree */ 1900 #ifdef DEBUG 1901 fprintf(stderr,"%s(%d) ", path, dpnt->depth); 1902 #endif 1903 if(parent->depth > RR_relocation_depth) 1904 { 1905 fprintf(stderr,"Directories too deep %s\n", path); 1906 exit(1); 1907 } 1908 1909 dpnt->parent = parent; 1910 dpnt->depth = parent->depth + 1; 1911 1912 if(!parent->subdir) 1913 { 1914 parent->subdir = dpnt; 1915 } 1916 else 1917 { 1918 next_brother = parent->subdir; 1919 while(next_brother->next) next_brother = next_brother->next; 1920 next_brother->next = dpnt; 1921 } 1922 } 1923 1924 return dpnt; 1925 } 1926 1927 /* 1928 * Function: delete_directory 1929 * 1930 * Purpose: Locate a directory entry in the tree, create if needed. 1931 * 1932 * Arguments: 1933 */ 1934 static void FDECL2(delete_directory, struct directory *, parent, struct directory *, child) 1935 { 1936 struct directory * tdir; 1937 1938 if( child->contents != NULL ) 1939 { 1940 fprintf(stderr, "Unable to delete non-empty directory\n"); 1941 exit(1); 1942 } 1943 1944 free(child->whole_name); 1945 child->whole_name = NULL; 1946 1947 free(child->de_name); 1948 child->de_name = NULL; 1949 1950 #ifdef APPLE_HYB 1951 if (apple_both && child->hfs_ent) 1952 free(child->hfs_ent); 1953 #endif /* APPLE_HYB */ 1954 1955 if( parent->subdir == child ) 1956 { 1957 parent->subdir = child->next; 1958 } 1959 else 1960 { 1961 for( tdir = parent->subdir; tdir->next != NULL; tdir = tdir->next ) 1962 { 1963 if( tdir->next == child ) 1964 { 1965 tdir->next = child->next; 1966 break; 1967 } 1968 } 1969 if( tdir == NULL ) 1970 { 1971 fprintf(stderr, "Unable to locate child directory in parent list\n"); 1972 exit(1); 1973 } 1974 } 1975 free(child); 1976 return; 1977 } 1978 1979 int FDECL1(sort_tree, struct directory *, node){ 1980 struct directory * dpnt; 1981 int ret = 0; 1982 1983 dpnt = node; 1984 1985 while (dpnt){ 1986 ret = sort_n_finish(dpnt); 1987 if( ret ) 1988 { 1989 break; 1990 } 1991 1992 if(dpnt->subdir) sort_tree(dpnt->subdir); 1993 dpnt = dpnt->next; 1994 } 1995 return ret; 1996 } 1997 1998 void FDECL1(dump_tree, struct directory *, node){ 1999 struct directory * dpnt; 2000 2001 dpnt = node; 2002 2003 while (dpnt){ 2004 fprintf(stderr,"%4d %5d %s\n",dpnt->extent, dpnt->size, dpnt->de_name); 2005 if(dpnt->subdir) dump_tree(dpnt->subdir); 2006 dpnt = dpnt->next; 2007 } 2008 } 2009 2010 void FDECL1(update_nlink_field, struct directory *, node) 2011 { 2012 struct directory * dpnt; 2013 struct directory * xpnt; 2014 struct directory_entry * s_entry; 2015 int i; 2016 2017 dpnt = node; 2018 2019 while (dpnt) 2020 { 2021 if (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) { 2022 dpnt = dpnt->next; 2023 continue; 2024 } 2025 2026 /* 2027 * First, count up the number of subdirectories this guy has. 2028 */ 2029 for(i=0, xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next) 2030 if ((xpnt->dir_flags & INHIBIT_ISO9660_ENTRY) == 0) 2031 i++; 2032 /* 2033 * Next check to see if we have any relocated directories 2034 * in this directory. The nlink field will include these 2035 * as real directories when they are properly relocated. 2036 * 2037 * In the non-rockridge disk, the relocated entries appear 2038 * as zero length files. 2039 */ 2040 for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) 2041 { 2042 if( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0 && 2043 (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == 0) 2044 { 2045 i++; 2046 } 2047 } 2048 /* 2049 * Now update the field in the Rock Ridge entry. 2050 */ 2051 update_nlink(dpnt->self, i + 2); 2052 2053 /* 2054 * Update the '.' entry for this directory. 2055 */ 2056 update_nlink(dpnt->contents, i + 2); 2057 2058 /* 2059 * Update all of the '..' entries that point to this guy. 2060 */ 2061 for(xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next) 2062 update_nlink(xpnt->contents->next, i + 2); 2063 2064 if(dpnt->subdir) update_nlink_field(dpnt->subdir); 2065 dpnt = dpnt->next; 2066 } 2067 } 2068 2069 /* 2070 * something quick and dirty to locate a file given a path 2071 * recursively walks down path in filename until it finds the 2072 * directory entry for the desired file 2073 */ 2074 struct directory_entry * FDECL2(search_tree_file, struct directory *, 2075 node,char *, filename) 2076 { 2077 struct directory_entry * depnt; 2078 struct directory * dpnt; 2079 char * p1; 2080 char * rest; 2081 char * subdir; 2082 2083 /* 2084 * strip off next directory name from filename 2085 */ 2086 subdir = strdup(filename); 2087 2088 if( (p1=strchr(subdir, '/')) == subdir ) 2089 { 2090 fprintf(stderr,"call to search_tree_file with an absolute path, stripping\n"); 2091 fprintf(stderr,"initial path separator. Hope this was intended...\n"); 2092 memmove(subdir, subdir+1, strlen(subdir)-1); 2093 p1 = strchr(subdir, '/'); 2094 } 2095 2096 /* 2097 * do we need to find a subdirectory 2098 */ 2099 if (p1) 2100 { 2101 *p1 = '\0'; 2102 2103 #ifdef DEBUG_TORITO 2104 fprintf(stderr,"Looking for subdir called %s\n",p1); 2105 #endif 2106 2107 rest = p1+1; 2108 2109 #ifdef DEBUG_TORITO 2110 fprintf(stderr,"Remainder of path name is now %s\n", rest); 2111 #endif 2112 2113 dpnt = node->subdir; 2114 while( dpnt ) 2115 { 2116 #ifdef DEBUG_TORITO 2117 fprintf(stderr,"%4d %5d %s\n", dpnt->extent, dpnt->size, 2118 dpnt->de_name); 2119 #endif 2120 if (!strcmp(subdir, dpnt->de_name)) 2121 { 2122 #ifdef DEBUG_TORITO 2123 fprintf(stderr,"Calling next level with filename = %s", rest); 2124 #endif 2125 return(search_tree_file( dpnt, rest )); 2126 } 2127 dpnt = dpnt->next; 2128 } 2129 2130 /* if we got here means we couldnt find the subdir */ 2131 return (NULL); 2132 } 2133 else 2134 { 2135 /* 2136 * look for a normal file now 2137 */ 2138 depnt = node->contents; 2139 while (depnt) 2140 { 2141 #ifdef DEBUG_TORITO 2142 fprintf(stderr,"%4d %5d %s\n",depnt->isorec.extent, 2143 depnt->size, depnt->name); 2144 #endif 2145 if (!strcmp(filename, depnt->name)) 2146 { 2147 #ifdef DEBUG_TORITO 2148 fprintf(stderr,"Found our file %s", filename); 2149 #endif 2150 return(depnt); 2151 } 2152 depnt = depnt->next; 2153 } 2154 /* 2155 * if we got here means we couldnt find the subdir 2156 */ 2157 return (NULL); 2158 } 2159 fprintf(stderr,"We cant get here in search_tree_file :-/ \n"); 2160 } 2161 2162 void init_fstatbuf() 2163 { 2164 time_t current_time; 2165 2166 if(fstatbuf.st_ctime == 0) 2167 { 2168 time (¤t_time); 2169 if( rationalize ) 2170 { 2171 fstatbuf.st_uid = 0; 2172 fstatbuf.st_gid = 0; 2173 } 2174 else 2175 { 2176 fstatbuf.st_uid = getuid(); 2177 fstatbuf.st_gid = getgid(); 2178 } 2179 fstatbuf.st_ctime = current_time; 2180 fstatbuf.st_mtime = current_time; 2181 fstatbuf.st_atime = current_time; 2182 } 2183 } 2184