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