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