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; 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 if (x_hfs = hfs_matches(short_name) || hfs_matches(whole_path)) { 1267 if (verbose > 1) { 1268 fprintf(stderr, "Hidden from HFS tree: %s\n", whole_path); 1269 } 1270 } 1271 } 1272 1273 /* check we are a file, using Apple extensions and have a .resource part 1274 and not excluded */ 1275 if (S_ISREG(lstatbuf.st_mode) && !have_rsrc && apple_both && !x_hfs) { 1276 char rsrc_path[1024]; /* rsrc fork filename */ 1277 1278 /* construct the resource full path */ 1279 htype = get_hfs_rname(whole_path, short_name, rsrc_path); 1280 /* check we can read the resouce fork */ 1281 if (htype) { 1282 struct stat rstatbuf, rlstatbuf; 1283 1284 /* some further checks on the file */ 1285 status = stat_filter(rsrc_path, &rstatbuf); 1286 1287 lstatus = lstat_filter(rsrc_path, &rlstatbuf); 1288 1289 if(!status && !lstatus && S_ISREG(rstatbuf.st_mode) && rstatbuf.st_size > 0) { 1290 /* have a resource file - insert it into the current directory 1291 but flag that we have a resource fork */ 1292 insert_file_entry(this_dir, rsrc_path, short_name, htype); 1293 } 1294 } 1295 } 1296 #endif /* APPLE_HYB */ 1297 1298 s_entry = (struct directory_entry *) 1299 e_malloc(sizeof (struct directory_entry)); 1300 /* memset the whole struct, not just the isorec.extent part JCP */ 1301 memset(s_entry, 0, sizeof (struct directory_entry)); 1302 s_entry->next = this_dir->contents; 1303 /*memset(s_entry->isorec.extent, 0, 8); */ 1304 this_dir->contents = s_entry; 1305 deep_flag = 0; 1306 s_entry->table = NULL; 1307 1308 s_entry->name = strdup(short_name); 1309 s_entry->whole_name = strdup (whole_path); 1310 1311 s_entry->de_flags = 0; 1312 1313 /* 1314 * If the current directory is hidden, then hide all it's members 1315 * otherwise check if this entry needs to be hidden as well */ 1316 if (this_dir->dir_flags & INHIBIT_ISO9660_ENTRY) { 1317 s_entry->de_flags |= INHIBIT_ISO9660_ENTRY; 1318 } 1319 else if (strcmp(short_name,".") && strcmp(short_name,"..")) { 1320 if (i_matches(short_name) || i_matches(whole_path)) { 1321 if (verbose > 1) { 1322 fprintf(stderr, "Hidden from ISO9660 tree: %s\n", whole_path); 1323 } 1324 s_entry->de_flags |= INHIBIT_ISO9660_ENTRY; 1325 } 1326 } 1327 1328 if (this_dir != reloc_dir && this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) { 1329 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; 1330 } 1331 else if (strcmp(short_name,".") && strcmp(short_name,"..")) { 1332 if (j_matches(short_name) || j_matches(whole_path)) { 1333 if (verbose > 1) { 1334 fprintf(stderr, "Hidden from Joliet tree: %s\n", whole_path); 1335 } 1336 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; 1337 } 1338 } 1339 1340 s_entry->filedir = this_dir; 1341 s_entry->isorec.flags[0] = 0; 1342 s_entry->isorec.ext_attr_length[0] = 0; 1343 iso9660_date(s_entry->isorec.date, statbuf.st_mtime); 1344 s_entry->isorec.file_unit_size[0] = 0; 1345 s_entry->isorec.interleave[0] = 0; 1346 1347 #ifdef APPLE_HYB 1348 if (apple_both && !x_hfs) { 1349 s_entry->hfs_ent = NULL; 1350 s_entry->assoc = NULL; 1351 s_entry->hfs_off = 0; 1352 s_entry->hfs_type = htype; 1353 if (have_rsrc) { 1354 s_entry->isorec.flags[0] = ASSOC_FLAG; /* associated (rsrc) file */ 1355 /* set the type of HFS file */ 1356 s_entry->hfs_type = have_rsrc; 1357 /* don't want the rsrc file to be included in any Joliet tree */ 1358 s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; 1359 } 1360 else if (s_entry->next) { 1361 /* if previous entry is an associated file, then "link" it 1362 to this file i.e. we have a data/resource pair */ 1363 if (s_entry->next->isorec.flags[0] & ASSOC_FLAG) { 1364 s_entry->assoc = s_entry->next; 1365 /* share the same HFS parameters */ 1366 s_entry->hfs_ent = s_entry->next->hfs_ent; 1367 s_entry->hfs_type = s_entry->next->hfs_type; 1368 } 1369 } 1370 /* allocate HFS entry if required */ 1371 if (apple_both && strcmp(short_name, ".") && strcmp(short_name, "..")) { 1372 if (!s_entry->hfs_ent) { 1373 hfsdirent *hfs_ent; 1374 hfs_ent = (hfsdirent *)e_malloc(sizeof(hfsdirent)); 1375 1376 /* fill in the defaults */ 1377 hfs_ent->flags = hfs_ent->fdflags = 0; 1378 hfs_ent->crdate = lstatbuf.st_ctime; 1379 hfs_ent->mddate = lstatbuf.st_mtime; 1380 hfs_ent->dsize = hfs_ent->rsize = 0; 1381 s_entry->hfs_ent = hfs_ent; 1382 } 1383 if (have_rsrc) 1384 /* set rsrc size */ 1385 s_entry->hfs_ent->rsize = lstatbuf.st_size; 1386 else 1387 /* set data size */ 1388 s_entry->hfs_ent->dsize = lstatbuf.st_size; 1389 } 1390 } 1391 #endif /* APPLE_HYB */ 1392 1393 if( strcmp(short_name, ".") == 0) 1394 { 1395 this_dir->dir_flags |= DIR_HAS_DOT; 1396 } 1397 1398 if( strcmp(short_name, "..") == 0) 1399 { 1400 this_dir->dir_flags |= DIR_HAS_DOTDOT; 1401 } 1402 1403 if( this_dir->parent 1404 && this_dir->parent == reloc_dir 1405 && strcmp(short_name, "..") == 0) 1406 { 1407 s_entry->inode = UNCACHED_INODE; 1408 s_entry->dev = (dev_t) UNCACHED_DEVICE; 1409 deep_flag = NEED_PL; 1410 } 1411 else 1412 #ifdef APPLE_HYB 1413 if (have_rsrc) { 1414 /* don't want rsrc files to be cached */ 1415 s_entry->inode = UNCACHED_INODE; 1416 s_entry->dev = (dev_t) UNCACHED_DEVICE; 1417 } 1418 else 1419 #endif /* APPLE_HYB */ 1420 { 1421 s_entry->inode = STAT_INODE(statbuf); 1422 s_entry->dev = statbuf.st_dev; 1423 } 1424 set_723(s_entry->isorec.volume_sequence_number, volume_sequence_number); 1425 iso9660_file_length(short_name, s_entry, S_ISDIR(statbuf.st_mode)); 1426 s_entry->rr_attr_size = 0; 1427 s_entry->total_rr_attr_size = 0; 1428 s_entry->rr_attributes = NULL; 1429 1430 /* Directories are assigned sizes later on */ 1431 if (!S_ISDIR(statbuf.st_mode)) 1432 { 1433 if (S_ISCHR(lstatbuf.st_mode) || S_ISBLK(lstatbuf.st_mode) || 1434 S_ISFIFO(lstatbuf.st_mode) || S_ISSOCK(lstatbuf.st_mode) 1435 || S_ISLNK(lstatbuf.st_mode)) 1436 { 1437 s_entry->size = 0; 1438 statbuf.st_size = 0; 1439 } 1440 else 1441 { 1442 s_entry->size = statbuf.st_size; 1443 } 1444 1445 set_733((char *) s_entry->isorec.size, statbuf.st_size); 1446 } 1447 else 1448 { 1449 s_entry->isorec.flags[0] = 2; 1450 } 1451 #ifdef APPLE_HYB 1452 /* if the directory is HFS excluded, then we don't have an hfs_ent */ 1453 if (apple_both && s_entry->hfs_ent && s_entry->isorec.flags[0] & 2) { 1454 /* get the Mac directory name */ 1455 get_hfs_dir(whole_path, short_name, s_entry); 1456 1457 /* if required, set ISO directory name from HFS name */ 1458 if (mac_name) 1459 iso9660_file_length(s_entry->hfs_ent->name, s_entry, 1); 1460 } 1461 #endif /* APPLE_HYB */ 1462 1463 if (strcmp(short_name,".") && strcmp(short_name,"..") && 1464 S_ISDIR(statbuf.st_mode) && this_dir->depth > RR_relocation_depth) 1465 { 1466 struct directory * child; 1467 1468 if(!reloc_dir) generate_reloc_directory(); 1469 1470 /* 1471 * Replicate the entry for this directory. The old one will stay where it 1472 * is, and it will be neutered so that it no longer looks like a directory. 1473 * The new one will look like a directory, and it will be put in the reloc_dir. 1474 */ 1475 s_entry1 = (struct directory_entry *) 1476 e_malloc(sizeof (struct directory_entry)); 1477 memcpy(s_entry1, s_entry, sizeof(struct directory_entry)); 1478 s_entry1->table = NULL; 1479 s_entry1->name = strdup(this_dir->contents->name); 1480 s_entry1->whole_name = strdup(this_dir->contents->whole_name); 1481 s_entry1->next = reloc_dir->contents; 1482 reloc_dir->contents = s_entry1; 1483 s_entry1->priority = 32768; 1484 s_entry1->parent_rec = this_dir->contents; 1485 1486 deep_flag = NEED_RE; 1487 1488 if(use_RockRidge) 1489 { 1490 generate_rock_ridge_attributes(whole_path, 1491 short_name, s_entry1, 1492 &statbuf, &lstatbuf, deep_flag); 1493 } 1494 1495 deep_flag = 0; 1496 1497 /* We need to set this temporarily so that the parent to this 1498 is correctly determined. */ 1499 s_entry1->filedir = reloc_dir; 1500 child = find_or_create_directory(reloc_dir, whole_path, 1501 s_entry1, 0); 1502 scan_directory_tree(child, whole_path, s_entry1); 1503 s_entry1->filedir = this_dir; 1504 1505 statbuf.st_size = 0; 1506 statbuf.st_mode &= 0777; 1507 set_733((char *) s_entry->isorec.size, 0); 1508 s_entry->size = 0; 1509 s_entry->isorec.flags[0] = 0; 1510 s_entry->inode = UNCACHED_INODE; 1511 s_entry->de_flags |= RELOCATED_DIRECTORY; 1512 deep_flag = NEED_CL; 1513 } 1514 1515 if(generate_tables 1516 && strcmp(s_entry->name, ".") 1517 && strcmp(s_entry->name, "..")) 1518 { 1519 char buffer[2048]; 1520 int nchar; 1521 switch(lstatbuf.st_mode & S_IFMT) 1522 { 1523 case S_IFDIR: 1524 snprintf(buffer, sizeof buffer, "D\t%s\n", 1525 s_entry->name); 1526 break; 1527 #ifdef S_IFBLK 1528 /* extra for WIN32 - if it doesn't have the major/minor defined, then 1529 S_IFBLK and S_IFCHR type files are unlikely to exist anyway ... 1530 code similar to that in rock.c */ 1531 1532 /* for some reason, MAJOR_IN_SYSMACROS isn't defined on a SunOS when 1533 it should be, so see if major() is defined instead */ 1534 /* 1535 #if !(defined(MAJOR_IN_SYSMACROS) || defined(MAJOR_IN_MKDEV)) 1536 */ 1537 #ifndef major 1538 #define major(dev) (sizeof(dev_t) <= 2 ? ((dev) >> 8) : \ 1539 (sizeof(dev_t) <= 4 ? (((dev) >> 8) >> 8) : \ 1540 (((dev) >> 16) >> 16))) 1541 #define minor(dev) (sizeof(dev_t) <= 2 ? (dev) & 0xff : \ 1542 (sizeof(dev_t) <= 4 ? (dev) & 0xffff : \ 1543 (dev) & 0xffffffff)) 1544 #endif 1545 case S_IFBLK: 1546 snprintf(buffer, sizeof buffer, "B\t%s\t%lu %lu\n", 1547 s_entry->name, 1548 (unsigned long) major(statbuf.st_rdev), 1549 (unsigned long) minor(statbuf.st_rdev)); 1550 break; 1551 #endif 1552 #ifdef S_IFIFO 1553 case S_IFIFO: 1554 snprintf(buffer, sizeof buffer, "P\t%s\n", 1555 s_entry->name); 1556 break; 1557 #endif 1558 #ifdef S_IFCHR 1559 case S_IFCHR: 1560 snprintf(buffer, sizeof buffer, "C\t%s\t%lu %lu\n", 1561 s_entry->name, 1562 (unsigned long) major(statbuf.st_rdev), 1563 (unsigned long) minor(statbuf.st_rdev)); 1564 break; 1565 #endif 1566 #ifdef S_IFLNK 1567 case S_IFLNK: 1568 nchar = readlink(whole_path, 1569 (char *)symlink_buff, 1570 sizeof(symlink_buff)-1); 1571 symlink_buff[nchar < 0 ? 0 : nchar] = 0; 1572 snprintf(buffer, sizeof buffer, "L\t%s\t%s\n", 1573 s_entry->name, symlink_buff); 1574 break; 1575 #endif 1576 #ifdef S_IFSOCK 1577 case S_IFSOCK: 1578 snprintf(buffer, sizeof buffer, "S\t%s\n", 1579 s_entry->name); 1580 break; 1581 #endif 1582 case S_IFREG: 1583 default: 1584 snprintf(buffer, sizeof buffer, "F\t%s\n", 1585 s_entry->name); 1586 break; 1587 }; 1588 s_entry->table = strdup(buffer); 1589 } 1590 1591 if(S_ISDIR(statbuf.st_mode)) 1592 { 1593 int dflag; 1594 if (strcmp(short_name,".") && strcmp(short_name,"..")) 1595 { 1596 struct directory * child; 1597 1598 child = find_or_create_directory(this_dir, whole_path, 1599 s_entry, 1); 1600 dflag = scan_directory_tree(child, whole_path, s_entry); 1601 1602 if(!dflag) 1603 { 1604 lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG; 1605 if( child->contents == NULL ) 1606 { 1607 delete_directory(this_dir, child); 1608 } 1609 } 1610 } 1611 /* If unable to scan directory, mark this as a non-directory */ 1612 } 1613 1614 if(use_RockRidge && this_dir == root && strcmp(s_entry->name, ".") == 0) 1615 { 1616 deep_flag |= NEED_CE | NEED_SP; /* For extension record */ 1617 } 1618 1619 /* Now figure out how much room this file will take in the 1620 directory */ 1621 1622 #ifdef APPLE_HYB 1623 /* if the file is HFS excluded, then we don't have an hfs_ent */ 1624 if (apple_both && !have_rsrc && s_entry->hfs_ent) { 1625 if (S_ISREG(lstatbuf.st_mode)) { /* it's a regular file */ 1626 1627 /* fill in the rest of the HFS entry */ 1628 get_hfs_info(whole_path, short_name, s_entry); 1629 1630 /* if required, set ISO directory name from HFS name */ 1631 if (mac_name) 1632 iso9660_file_length(s_entry->hfs_ent->name, s_entry, 0); 1633 1634 /* print details about the HFS file */ 1635 if (verbose > 2) 1636 print_hfs_info(s_entry); 1637 1638 /* copy the new ISO9660 name to the rsrc fork - if it exists */ 1639 if (s_entry->assoc) 1640 strcpy(s_entry->assoc->isorec.name, s_entry->isorec.name); 1641 1642 /* we can't handle hard links in the hybrid case, so we "uncache" 1643 the file. The downside to this is that hard linked files 1644 are added to the output image more than once (we've already 1645 done this for rsrc files) */ 1646 if (apple_hyb) { 1647 s_entry->inode = UNCACHED_INODE; 1648 s_entry->dev = (dev_t) UNCACHED_DEVICE; 1649 } 1650 } 1651 else if (!(s_entry->isorec.flags[0] & 2)) { /* not a directory .. */ 1652 1653 /* no mac equivalent, so ignore - have to be careful here, the 1654 hfs_ent may be also be for a relocated directory */ 1655 if (s_entry->hfs_ent && !(s_entry->de_flags & RELOCATED_DIRECTORY)) 1656 free(s_entry->hfs_ent); 1657 s_entry->hfs_ent = NULL; 1658 } 1659 1660 /* if the rsrc size is zero, then we don't need the entry, so we 1661 might as well delete it - this will only happen if we didn't 1662 know the rsrc size from the rsrc file size */ 1663 if(s_entry->assoc && s_entry->assoc->size == 0) 1664 delete_rsrc_ent(s_entry); 1665 } 1666 1667 if(apple_ext && s_entry->assoc) { 1668 /* need Apple extensions for the resource fork as well */ 1669 generate_rock_ridge_attributes(whole_path, 1670 short_name, s_entry->assoc, 1671 &statbuf, &lstatbuf, deep_flag); 1672 } 1673 /* leave out resource fork for the time being */ 1674 if (use_RockRidge && !have_rsrc) { 1675 #else 1676 if(use_RockRidge) 1677 { 1678 #endif /* APPLE_HYB */ 1679 generate_rock_ridge_attributes(whole_path, 1680 short_name, s_entry, 1681 &statbuf, &lstatbuf, deep_flag); 1682 1683 } 1684 1685 return 1; 1686 } 1687 1688 1689 void FDECL2(generate_iso9660_directories, struct directory *, node, FILE*, outfile){ 1690 struct directory * dpnt; 1691 1692 dpnt = node; 1693 1694 while (dpnt){ 1695 if( dpnt->extent > session_start ) 1696 { 1697 generate_one_directory(dpnt, outfile); 1698 } 1699 if(dpnt->subdir) generate_iso9660_directories(dpnt->subdir, outfile); 1700 dpnt = dpnt->next; 1701 } 1702 } 1703 1704 /* 1705 * Function: find_or_create_directory 1706 * 1707 * Purpose: Locate a directory entry in the tree, create if needed. 1708 * 1709 * Arguments: 1710 */ 1711 struct directory * FDECL4(find_or_create_directory, struct directory *, parent, 1712 const char *, path, 1713 struct directory_entry *, de, int, flag) 1714 { 1715 struct directory * dpnt; 1716 struct directory_entry * orig_de; 1717 struct directory * next_brother; 1718 const char * cpnt; 1719 const char * pnt; 1720 1721 orig_de = de; 1722 1723 pnt = strrchr(path, PATH_SEPARATOR); 1724 if( pnt == NULL ) 1725 { 1726 pnt = path; 1727 } 1728 else 1729 { 1730 pnt++; 1731 } 1732 1733 if( parent != NULL ) 1734 { 1735 dpnt = parent->subdir; 1736 1737 while (dpnt) 1738 { 1739 /* 1740 * Weird hack time - if there are two directories by the 1741 * same name in the reloc_dir, they are not treated as the 1742 * same thing unless the entire path matches completely. 1743 */ 1744 if( flag && strcmp(dpnt->de_name, pnt) == 0 ) 1745 { 1746 return dpnt; 1747 } 1748 dpnt = dpnt->next; 1749 } 1750 } 1751 1752 /* 1753 * We don't know if we have a valid directory entry for this one 1754 * yet. If not, we need to create one. 1755 */ 1756 if( de == NULL ) 1757 { 1758 de = (struct directory_entry *) 1759 e_malloc(sizeof (struct directory_entry)); 1760 memset(de, 0, sizeof(struct directory_entry)); 1761 de->next = parent->contents; 1762 parent->contents = de; 1763 de->name = strdup(pnt); 1764 de->filedir = parent; 1765 de->isorec.flags[0] = 2; 1766 de->priority = 32768; 1767 de->inode = UNCACHED_INODE; 1768 de->dev = (dev_t) UNCACHED_DEVICE; 1769 set_723(de->isorec.volume_sequence_number, volume_sequence_number); 1770 iso9660_file_length (pnt, de, 1); 1771 1772 init_fstatbuf(); 1773 /* 1774 * It doesn't exist for real, so we cannot add any Rock Ridge. 1775 */ 1776 if(use_RockRidge) 1777 { 1778 fstatbuf.st_mode = 0555 | S_IFDIR; 1779 fstatbuf.st_nlink = 2; 1780 generate_rock_ridge_attributes("", 1781 (char *) pnt, de, 1782 &fstatbuf, 1783 &fstatbuf, 0); 1784 } 1785 iso9660_date(de->isorec.date, fstatbuf.st_mtime); 1786 #ifdef APPLE_HYB 1787 if (apple_both) { 1788 /* give the directory an HFS entry */ 1789 hfsdirent *hfs_ent; 1790 hfs_ent = (hfsdirent *)e_malloc(sizeof(hfsdirent)); 1791 1792 /* fill in the defaults */ 1793 hfs_ent->flags = hfs_ent->fdflags = 0; 1794 hfs_ent->crdate = fstatbuf.st_ctime; 1795 hfs_ent->mddate = fstatbuf.st_mtime; 1796 hfs_ent->dsize = hfs_ent->rsize = 0; 1797 1798 de->hfs_ent = hfs_ent; 1799 1800 /* get the Mac directory name */ 1801 get_hfs_dir(path, pnt, de); 1802 } 1803 #endif /* APPLE_HYB */ 1804 } 1805 1806 /* 1807 * If we don't have a directory for this one yet, then allocate it 1808 * now, and patch it into the tree in the appropriate place. 1809 */ 1810 dpnt = (struct directory *) e_malloc(sizeof(struct directory)); 1811 memset(dpnt, 0, sizeof(struct directory)); 1812 dpnt->next = NULL; 1813 dpnt->subdir = NULL; 1814 dpnt->self = de; 1815 dpnt->contents = NULL; 1816 dpnt->whole_name = strdup(path); 1817 cpnt = strrchr(path, PATH_SEPARATOR); 1818 if(cpnt) 1819 cpnt++; 1820 else 1821 cpnt = path; 1822 dpnt->de_name = strdup(cpnt); 1823 dpnt->size = 0; 1824 dpnt->extent = 0; 1825 dpnt->jextent = 0; 1826 dpnt->jsize = 0; 1827 #ifdef APPLE_HYB 1828 dpnt->hfs_ent = de->hfs_ent; 1829 #endif /*APPLE_HYB */ 1830 1831 if( orig_de == NULL ) 1832 { 1833 struct stat xstatbuf; 1834 int sts; 1835 1836 /* 1837 * Now add a . and .. entry in the directory itself. 1838 * This is a little tricky - if the real directory 1839 * exists, we need to stat it first. Otherwise, we 1840 * use the fictitious fstatbuf which points to the time 1841 * at which mkisofs was started. 1842 */ 1843 sts = stat_filter(parent->whole_name, &xstatbuf); 1844 if( sts == 0 ) 1845 { 1846 attach_dot_entries(dpnt, &xstatbuf); 1847 } 1848 else 1849 { 1850 attach_dot_entries(dpnt, &fstatbuf); 1851 } 1852 } 1853 1854 if(!parent || parent == root) 1855 { 1856 if (!root) 1857 { 1858 root = dpnt; /* First time through for root directory only */ 1859 root->depth = 0; 1860 root->parent = root; 1861 } else { 1862 dpnt->depth = 1; 1863 if(!root->subdir) 1864 { 1865 root->subdir = dpnt; 1866 } 1867 else 1868 { 1869 next_brother = root->subdir; 1870 while(next_brother->next) next_brother = next_brother->next; 1871 next_brother->next = dpnt; 1872 } 1873 dpnt->parent = parent; 1874 } 1875 } 1876 else 1877 { 1878 /* Come through here for normal traversal of tree */ 1879 #ifdef DEBUG 1880 fprintf(stderr,"%s(%d) ", path, dpnt->depth); 1881 #endif 1882 if(parent->depth > RR_relocation_depth) 1883 { 1884 fprintf(stderr,"Directories too deep %s\n", path); 1885 exit(1); 1886 } 1887 1888 dpnt->parent = parent; 1889 dpnt->depth = parent->depth + 1; 1890 1891 if(!parent->subdir) 1892 { 1893 parent->subdir = dpnt; 1894 } 1895 else 1896 { 1897 next_brother = parent->subdir; 1898 while(next_brother->next) next_brother = next_brother->next; 1899 next_brother->next = dpnt; 1900 } 1901 } 1902 1903 return dpnt; 1904 } 1905 1906 /* 1907 * Function: delete_directory 1908 * 1909 * Purpose: Locate a directory entry in the tree, create if needed. 1910 * 1911 * Arguments: 1912 */ 1913 static void FDECL2(delete_directory, struct directory *, parent, struct directory *, child) 1914 { 1915 struct directory * tdir; 1916 1917 if( child->contents != NULL ) 1918 { 1919 fprintf(stderr, "Unable to delete non-empty directory\n"); 1920 exit(1); 1921 } 1922 1923 free(child->whole_name); 1924 child->whole_name = NULL; 1925 1926 free(child->de_name); 1927 child->de_name = NULL; 1928 1929 #ifdef APPLE_HYB 1930 if (apple_both && child->hfs_ent) 1931 free(child->hfs_ent); 1932 #endif /* APPLE_HYB */ 1933 1934 if( parent->subdir == child ) 1935 { 1936 parent->subdir = child->next; 1937 } 1938 else 1939 { 1940 for( tdir = parent->subdir; tdir->next != NULL; tdir = tdir->next ) 1941 { 1942 if( tdir->next == child ) 1943 { 1944 tdir->next = child->next; 1945 break; 1946 } 1947 } 1948 if( tdir == NULL ) 1949 { 1950 fprintf(stderr, "Unable to locate child directory in parent list\n"); 1951 exit(1); 1952 } 1953 } 1954 free(child); 1955 return; 1956 } 1957 1958 int FDECL1(sort_tree, struct directory *, node){ 1959 struct directory * dpnt; 1960 int ret = 0; 1961 1962 dpnt = node; 1963 1964 while (dpnt){ 1965 ret = sort_n_finish(dpnt); 1966 if( ret ) 1967 { 1968 break; 1969 } 1970 1971 if(dpnt->subdir) sort_tree(dpnt->subdir); 1972 dpnt = dpnt->next; 1973 } 1974 return ret; 1975 } 1976 1977 void FDECL1(dump_tree, struct directory *, node){ 1978 struct directory * dpnt; 1979 1980 dpnt = node; 1981 1982 while (dpnt){ 1983 fprintf(stderr,"%4d %5d %s\n",dpnt->extent, dpnt->size, dpnt->de_name); 1984 if(dpnt->subdir) dump_tree(dpnt->subdir); 1985 dpnt = dpnt->next; 1986 } 1987 } 1988 1989 void FDECL1(update_nlink_field, struct directory *, node) 1990 { 1991 struct directory * dpnt; 1992 struct directory * xpnt; 1993 struct directory_entry * s_entry; 1994 int i; 1995 1996 dpnt = node; 1997 1998 while (dpnt) 1999 { 2000 if (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) { 2001 dpnt = dpnt->next; 2002 continue; 2003 } 2004 2005 /* 2006 * First, count up the number of subdirectories this guy has. 2007 */ 2008 for(i=0, xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next) 2009 if ((xpnt->dir_flags & INHIBIT_ISO9660_ENTRY) == 0) 2010 i++; 2011 /* 2012 * Next check to see if we have any relocated directories 2013 * in this directory. The nlink field will include these 2014 * as real directories when they are properly relocated. 2015 * 2016 * In the non-rockridge disk, the relocated entries appear 2017 * as zero length files. 2018 */ 2019 for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) 2020 { 2021 if( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0 && 2022 (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) == 0) 2023 { 2024 i++; 2025 } 2026 } 2027 /* 2028 * Now update the field in the Rock Ridge entry. 2029 */ 2030 update_nlink(dpnt->self, i + 2); 2031 2032 /* 2033 * Update the '.' entry for this directory. 2034 */ 2035 update_nlink(dpnt->contents, i + 2); 2036 2037 /* 2038 * Update all of the '..' entries that point to this guy. 2039 */ 2040 for(xpnt = dpnt->subdir; xpnt; xpnt = xpnt->next) 2041 update_nlink(xpnt->contents->next, i + 2); 2042 2043 if(dpnt->subdir) update_nlink_field(dpnt->subdir); 2044 dpnt = dpnt->next; 2045 } 2046 } 2047 2048 /* 2049 * something quick and dirty to locate a file given a path 2050 * recursively walks down path in filename until it finds the 2051 * directory entry for the desired file 2052 */ 2053 struct directory_entry * FDECL2(search_tree_file, struct directory *, 2054 node,char *, filename) 2055 { 2056 struct directory_entry * depnt; 2057 struct directory * dpnt; 2058 char * p1; 2059 char * rest; 2060 char * subdir; 2061 2062 /* 2063 * strip off next directory name from filename 2064 */ 2065 subdir = strdup(filename); 2066 2067 if( (p1=strchr(subdir, '/')) == subdir ) 2068 { 2069 fprintf(stderr,"call to search_tree_file with an absolute path, stripping\n"); 2070 fprintf(stderr,"initial path separator. Hope this was intended...\n"); 2071 memmove(subdir, subdir+1, strlen(subdir)-1); 2072 p1 = strchr(subdir, '/'); 2073 } 2074 2075 /* 2076 * do we need to find a subdirectory 2077 */ 2078 if (p1) 2079 { 2080 *p1 = '\0'; 2081 2082 #ifdef DEBUG_TORITO 2083 fprintf(stderr,"Looking for subdir called %s\n",p1); 2084 #endif 2085 2086 rest = p1+1; 2087 2088 #ifdef DEBUG_TORITO 2089 fprintf(stderr,"Remainder of path name is now %s\n", rest); 2090 #endif 2091 2092 dpnt = node->subdir; 2093 while( dpnt ) 2094 { 2095 #ifdef DEBUG_TORITO 2096 fprintf(stderr,"%4d %5d %s\n", dpnt->extent, dpnt->size, 2097 dpnt->de_name); 2098 #endif 2099 if (!strcmp(subdir, dpnt->de_name)) 2100 { 2101 #ifdef DEBUG_TORITO 2102 fprintf(stderr,"Calling next level with filename = %s", rest); 2103 #endif 2104 return(search_tree_file( dpnt, rest )); 2105 } 2106 dpnt = dpnt->next; 2107 } 2108 2109 /* if we got here means we couldnt find the subdir */ 2110 return (NULL); 2111 } 2112 else 2113 { 2114 /* 2115 * look for a normal file now 2116 */ 2117 depnt = node->contents; 2118 while (depnt) 2119 { 2120 #ifdef DEBUG_TORITO 2121 fprintf(stderr,"%4d %5d %s\n",depnt->isorec.extent, 2122 depnt->size, depnt->name); 2123 #endif 2124 if (!strcmp(filename, depnt->name)) 2125 { 2126 #ifdef DEBUG_TORITO 2127 fprintf(stderr,"Found our file %s", filename); 2128 #endif 2129 return(depnt); 2130 } 2131 depnt = depnt->next; 2132 } 2133 /* 2134 * if we got here means we couldnt find the subdir 2135 */ 2136 return (NULL); 2137 } 2138 fprintf(stderr,"We cant get here in search_tree_file :-/ \n"); 2139 } 2140 2141 void init_fstatbuf() 2142 { 2143 time_t current_time; 2144 2145 if(fstatbuf.st_ctime == 0) 2146 { 2147 time (¤t_time); 2148 if( rationalize ) 2149 { 2150 fstatbuf.st_uid = 0; 2151 fstatbuf.st_gid = 0; 2152 } 2153 else 2154 { 2155 fstatbuf.st_uid = getuid(); 2156 fstatbuf.st_gid = getgid(); 2157 } 2158 fstatbuf.st_ctime = current_time; 2159 fstatbuf.st_mtime = current_time; 2160 fstatbuf.st_atime = current_time; 2161 } 2162 } 2163