diff options
| author | Joerg Wunsch <joerg@FreeBSD.org> | 1995-10-22 10:11:03 +0000 |
|---|---|---|
| committer | Joerg Wunsch <joerg@FreeBSD.org> | 1995-10-22 10:11:03 +0000 |
| commit | 3f2e9a763fabff16dd209e3f7c59c5922574682f (patch) | |
| tree | f5dea9912f17202d9e3dddd7cde2bdb65f77f7e5 | |
Notes
| -rw-r--r-- | gnu/usr.bin/mkisofs/ChangeLog | 695 | ||||
| -rw-r--r-- | gnu/usr.bin/mkisofs/Makefile.in | 51 | ||||
| -rw-r--r-- | gnu/usr.bin/mkisofs/README | 84 | ||||
| -rw-r--r-- | gnu/usr.bin/mkisofs/defaults.h | 25 | ||||
| -rw-r--r-- | gnu/usr.bin/mkisofs/diag/Makefile | 16 | ||||
| -rw-r--r-- | gnu/usr.bin/mkisofs/diag/isodump.c | 436 | ||||
| -rw-r--r-- | gnu/usr.bin/mkisofs/diag/isoinfo.c | 522 | ||||
| -rw-r--r-- | gnu/usr.bin/mkisofs/diag/isovfy.c | 490 | ||||
| -rw-r--r-- | gnu/usr.bin/mkisofs/exclude.c | 54 | ||||
| -rw-r--r-- | gnu/usr.bin/mkisofs/mkisofs.8 | 274 | ||||
| -rw-r--r-- | gnu/usr.bin/mkisofs/mkisofs.c | 721 | ||||
| -rw-r--r-- | gnu/usr.bin/mkisofs/mkisofs.h | 263 | ||||
| -rw-r--r-- | gnu/usr.bin/mkisofs/rock.c | 530 | ||||
| -rw-r--r-- | gnu/usr.bin/mkisofs/tree.c | 1012 | ||||
| -rw-r--r-- | gnu/usr.bin/mkisofs/write.c | 784 |
15 files changed, 5957 insertions, 0 deletions
diff --git a/gnu/usr.bin/mkisofs/ChangeLog b/gnu/usr.bin/mkisofs/ChangeLog new file mode 100644 index 000000000000..8dc41be1ffc9 --- /dev/null +++ b/gnu/usr.bin/mkisofs/ChangeLog @@ -0,0 +1,695 @@ +Sun Feb 26 01:52:06 1995 Eric Youngdale (eric@largo) + + * Add patches from Ross Biro to allow you to merge arbitrary + trees into the image. This is not compiled in by default but + you need to add -DADD_FILES when compiling. + +Fri Feb 17 02:29:03 1995 Paul Eggert <eggert@twinsun.com> + + * tree.c: Port to Solaris 2.4. Prefer <sys/mkdev.h> if + HASMKDEV. Cast unknown integer types to unsigned long and + print them with %lu or %lx. + +Thu Jan 26 15:25:00 1995 H. Peter Anvin (hpa@yggdrasil.com) + + * mkisofs.c: Substitute underscore for leading dot in non-Rock + Ridge filenames, since MS-DOS cannot read files whose names + begin with a period. + +Mon Jan 16 18:31:41 1995 Eric Youngdale (eric@aib.com) + + * rock.c (generate_rock_ridge_attributes): Only use ROOT + record for symlinks if we are at the start of the symlink. + Otherwise just generate an empty entry. + +Mon Jan 16 16:19:50 1995 Eric Youngdale (eric@aib.com) + + * diag/isodump.c: Use isonum_733 instead of trying to dereference + pointers when trying to decode 733 numbers in the iso9660 image. + + * diag/isovfy.c: Likewise. + + * write.c: Always assign an extent number, even for zero length + files. A zero length file with a NULL extent is apparently dropped + by many readers. + +Wed Jan 11 13:46:50 1995 Eric Youngdale (eric@aib.com) + + * mkisofs.c: Modify extension record to conform to IEEE P1282 + specifications. This is commented out right now, but a trivial + change to a #define enables this. I need to see the specs + to see whether anything else changed before this becomes final. + + * write.c (FDECL4): Fix so that we properly determine error + conditions. + + * mkisofs.h: Change rr_attributes to unsigned. + + * tree.c(increment_nlink): Change pnt since rr_attributes is now + unsigned. + + Ultrix patches from petav@argon.e20.physik.tu-muenchen.de (Peter Averkamp) + + * rock.c: Fix for ultrix systems, we have 64 bit device numbers. + Type cast when generating file size. Change rr_attributes to + unsigned. + + * mkisofs.c: For ultrix systems, define our own function + for strdup. + + * mkisofs.c: Fix usage() since some compilers do not concatenate + strings properly (i.e. ultrix). + + Bugs found with Sentinel II: + + * write.c: Fix a couple of memory leaks. + + * mkisofs.c: Bugfix - always put a zero byte at end of name + for ".." entry. + + * tree.c: Set isorec.date from fstatbuf.st_ctime, not current_time, + since current_time might not be set. + +Sat Dec 3 14:55:42 1994 Eric Youngdale (eric@andante) + + * mkisofs.c: When returning entry for ".." file, set second byte + to 0. + + * write.c: Free name and rr_attributes fields when writing. + +Mon Nov 28 13:36:27 1994 Eric Youngdale (eric@andante) + + * mkisofs.h: Change rr_attributes to unsigned. + + * rock.c: Ditto. Work around >>32 bug in ultrix for 64 bit data types. + + * mkisofs.c (usage): Fix for ultrix - use continuation lines + instead of assuming that strings are catenated by the compiler. + +Mon Jun 20 20:25:26 1994 Eric Youngdale (eric@esp22) + + * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to pre-1.02. + + * mkisofs.h: Fix declaration of e_malloc to use DECL macros. + + * tree.c: Fix bug in previous change. + + * diag/*.c: Add appropriate copyright notices. + +Sat Apr 9 13:30:46 1994 Eric Youngdale (ericy@cais.com) + + * Configure: New file - shell script that determines a bunch of + things to properly build mkisofs. + + * Makefile.in: New file - copy of Makefile, but Configure sets a + few things up for it. + + * tree.c: Do not depend upon opendir to return NULL if we cannot + open a directory - actually try and read the first entry. The + foibles of NFS seem to require this. + + * write.c: Fix definition of xfwrite (Use FDECL4) + + Add some changes to allow more configurability of some of the + volume header fields: + + * mkisofs.8: Document new configuration options. + + * mkisofs.c: Add variables to hold new fields. Add function to + read .mkisofsrc files. + + * defaults.h: Another way of configuring the same things. + + Add some changes from Leo Weppelman leo@ahwau.ahold.nl. + + * mkisofs.c: Allow -A to specify application ID. Fix usage(), + getopt and add case switch. + + * rock.c: Fix handling of device numbers (dev_t high should only + be used when sizeof(dev_t) > 32 bits). + + Add a bunch of changes from Manuel Bouyer. + + * diag/Makefile: New file. + + * diag/dump.c, diag/isodump.c: Use termios if system supports it. + + * (throughout): Replace all occurences of "malloc" with e_malloc. + + * mkisofs.c: For NetBSD, attempt to increase the rlimit for + the size of the data segment to about 33 Mb. + + * mkisofs.c (e_malloc): New function. Calls malloc, and prints + nice error message and exits if NULL is returned. + +Sun Jan 23 19:23:57 1994 Eric Youngdale (eric@esp22) + + * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.01. + + Add a bunch of stuff so that mkisofs will work on a VMS system. + + * (ALL): Change any direct use of the "st_ino" field from + the statbuf to use a macro. + + * mkisofs.h: Define appropriate macros for both VMS and unix. + + * (ALL): Add type casts whenever we use the UNCACHED_DEV macro. + + * rock.c: Wrap a #ifndef VMS around block and character device + stuff. + + * write.c: Add prototype for strdup if VMS is defined. + + * make.com: Script for building mkisofs on a VMS system. + + * Makefile: Include make.com in the distribution. + + * mkisofs.c: Include <sys/type.h> on VMS systems. + + * tree.c: Include <sys/file.h> and "vms.h" on VMS systems. + + * mkisofs.h (PATH_SEPARATOR, SPATH_SEPARATOR): New macros + that define the ascii character that separates the last directory + component from the filename. + + * tree.c, mkisofs.c: Use them. + + * vms.c: New file. Contains version of getopt, strdup, opendir, + readdir and closedir. + + * vms.h: New file. Defines S_IS* macros. Define gmtime as + localtime, since gmtime under VMS returns NULL. + +Sat Jan 15 13:57:42 1994 Eric Youngdale (eric@esp22) + + * mkisofs.h (transparent_compression): New prototype. + + * mkisofs.c (transparent_compression): Declare, use + '-z' option to turn on. + + * tree.c: Change TRANS.TBL;1 to TRANS.TBL (version gets + added later, if required). + + * rock.c: If transparent compression requested, verify + file is really suitable (check magic numbers), and extract + correct file length to store in SUSP record. + +Sat Jan 15 01:57:42 1994 Eric Youngdale (eric@esp22) + + * write.c (compare_dirs): Bugfix for patch from Jan 6. + + * mkisofs.h (struct directory_entry): Add element total_rr_attr_size. + (struct file_hash): Add element ce_bytes. + + * write.c (iso_write): Update last_extent_written, as required, + and check it against last_extent as a sanity check. + (generate_one_directory): If ce_bytes is non-zero, allocate + a buffer and fill it with the CE records. Also, update + the extent and offset entries in the CE SUSP field and + output after directory is written. + (assign_directory_addresses): Allow for CE sectors after each + directory. + + * tree.c (sort_n_finish): Set field ce_bytes by summing + the sizes of all CE blocks in each files RR attributes. + Do not count these bytes for main directory. + + * rock.c (generate_rock_ridge_attributes): Generate + CE entries to break up large records into manageable sizes. + Allow long names to be split, and allow long symlinks to be split. + Allow splitting before each SUSP field as well, to make + sure we do not screw outselves. + +Thu Jan 6 21:47:43 1994 Eric Youngdale (eric@esp22) + + Bugfix. + + * write.c (compare_dirs): Only compare directory names up to + the ';' for the version number. + + Add four new options: (1) Full 31 character filenames, + (2) Omit version number, (3) Omit trailing period from filenames, + (4) Skip deep directory relocation. + + * iso9660.h: Allow 34 characters for filename. + + * mkisofs.8: Update for new options. + + * mkisofs.c: Add flag variables for new options. + Mention new options in usage(), tell getopt about + new options, and set appropriate flags when + new options are specified. + + * mkisofs.c (iso9660_file_length): Implement new options. + + * mkisofs.h: Declare flag variables for new options. + + * tree.c (sort_n_finish): Increase declaration of newname and + rootname to 34 characters. If full_iso9660_filenames in effect, + use different rules for making unique names. + + * tree.c (scan_directory_tree): Use RR_relocation_depth instead of + constant for threshold for starting deep directory relocation. + +Wed Jan 5 01:32:34 1994 John Brezak (brezak@ch.hp.com) + + * Makefile.bsd: New file. For NetBSD. + + * rock.c, tree.c: Do not include sys/sysmacros.h for NetBSD. + +Fri Dec 31 13:22:52 1993 Eric Youngdale (eric@esp22) + + * mkisofs.c, mkisofs.8, Makefile (version_string): Bump to 1.00. + + * tree.c (scan_directory_tree): Handle case where we do not + have permissions to open a directory. + + * write.c (xfwrite): New function - wrapper for fwrite, + except that we print message and punt if write fails. + + * write.c: Move include of mkisofs.h and iso9660.h until after + string.h and stdlib.h is included. + + * write.c: Do not attempt to use strerror on sun systems. + +Thu Dec 9 13:17:28 1993 R.-D. Marzusch (marzusch@odiehh.hanse.de) + + * exclude.c, exclude.h: New files. Contains list of files to + exclude from consideration. + + * Makefile: Compile exclude.c, add dependencies to other files. + + * mkisofs.8: Describe -x option. + + * mkisofs.c: Include exclude.h, handle -x option. + + +Fri Dec 10 01:07:43 1993 Peter van der Veen (peterv@qnx.com) + + * mkisofs.c, mkisofs.h: Moved declaration of root_record. + + * mkisofs.h: Added prototype for get_733(). + + * write.c(iso_write), tree.c, rock.c(generate_rock_ridge_attributes): + Added defines for QNX operation system + + * rock.c(generate_rock_ridge_attributes): symbolic links should + not have CONTINUE component flag set unless there are multiple + component records, and mkisofs does not generate these. + st_ctime was stored as the creation time, changed to attribute time. + QNX has a creation time, so that is stored as well under QNX. + +Thu Oct 28 19:54:38 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.99. + + * write.c(iso_write): Put hour, minute, second into date fields in + volume descriptor. + + * write.c (iso_write): Set file_structure_version to 1, instead of + ' ' (Seems to screw up Macs). + +Sun Oct 17 01:13:36 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.98. + + Increment nlink in root directory when rr_moved directory is present. + + * tree.c (increment_nlink): New function. + + * tree.c (finish_cl_pl_entries): Call increment_nlink for all + references to the root directory. + + * tree.c (root_statbuf): New variable. + + * tree.c (scan_directory_tree): Initialize root_statbuf when we + stat the root directory. + + * tree.c (generate_reloc_directory): Use root_statbuf when + generating the Rock Ridge stuff for the ".." entry in the + reloc_dir. + + * tree.c (scan_directory_tree): Use root_statbuf when generating + the ".." entry in the root directory. + +Sat Oct 16 10:28:30 1993 Eric Youngdale (eric@kafka) + + Fix path tables so that they are sorted. + + * tree.c (assign_directory_addresses): Move to write.c + + * write.c (generate_path_tables): Create an array of pointers to + the individual directories, and sort it based upon the name and + the parent path table index. Then update all of the indexes and + repeat the sort until the path table indexes no longer need to be + changed, and then write the path table. + + Fix problem where hard links were throwing off the total extent count. + + * write.c (iso_write): Call assign_file_addresses, and then + use last_extent to determine how big the volume is. + + * write.c (generate_one_directory): Decrement n_data_extents + for hard links to non-directories so that the expected number + of extents is written correctly. + + * write.c(assign_file_addresses): New function. + +Fri Oct 15 22:35:43 1993 Eric Youngdale (eric@kafka) + + The standard says we should do these things: + + * tree.c (generate_reloc_directory): Add RR attributes to + the rr_moved directory. + + * mkisofs.c(main): Change ER text strings back to recommended + values. + +Tue Oct 12 21:07:38 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.97. + + * tree.c (scan_directory_tree): Do not insert PL entry into + root directory record (i.e. !parent) + + * tree.c (finish_cl_pl_entries): Do not rely upon name + comparison to locate parent - use d_entry->self instead, + which is guaranteed to be correct. + + * mkisofs.h: New variable n_data_extents. + + * tree.c: Declare and initialize n_data_extents to 0. + (scan_directory_tree) for non-directories, add + ROUND_UP(statbuf.st_size) to n_data_extents. + (sort_n_finish): Increment n_data_extents for translation tables, + as appropriate. + + * write.c(iso_write): Add n_data_extents to the + volume_space_size field. + + * hash.c(add_hash): If size != 0 and extent == 0, or + if size == 0 and extent != 0, then complain about + inserting this into the hash table. Kind of a sanity check. + +Sat Oct 9 16:39:15 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.96. + + Numerous bugfixes, thanks to a one-off disc from rab@cdrom.com. + + * write.c(generate_one_directory): Wait until after we have + filled in the starting_extent field to s_entry before calling + add_hash. This fixes a problem where the hash table gets an + extent of 0 for all regular files, and this turns up when you have + hard links on the disc. (The hash table allows us to have each + hard link point to the same extent on the cdrom, thereby saving + some space). + + * tree.c(scan_directory_tree): Set statbuf.st_dev and + statbuf.st_ino to the UNCACHED numbers for symlinks that we + are not following. This prevents the function find_hash from + returning an inode that cooresponds to the file the symlink points + to, which in turn prevents generate_one_directory from filling in + a bogus file length (should be zero for symlinks). + + * tree.c(scan_directory_tree): Always call lstat for the file + so that non-RockRidge discs get correct treatment of symlinks. + Improve error message when we ignore a symlink on a non-RR disc. + + * write.c(generate_one_directory): Set fields for starting_extent + and size in the "." and ".." entries before we add them to the + file hash. Fixes problems with incorrect backlinks for second + level directories. + +Wed Oct 6 19:53:40 1993 Eric Youngdale (eric@kafka) + + * write.c (write_one_file): Print message and punt if we are + unable to open the file. + + * tree.c(scan_directory_tree): For regular files, use the access + function to verify that the file is readable in the first place. + If not, issue a warning and skip it. For directories, it probably + does not matter, since we would not be able to descend into them + in the first place. + +Wed Sep 29 00:02:47 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.95. + + * write.c, tree.c: Cosmetic changes to printed information. + + * tree.c(scan_directory_tree): Set size to zero for + special stub entries that correspond to the + relocated directories. Hopefully last big bug. + + * mkisofs.h: Change TABLE_INODE, UNCACHED_* macros + to be 0x7fff... to be compatible with signed datatypes. + +Mon Sep 27 20:14:49 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.94. + + * write.c (write_path_tables): Actually search the + directory for the matching entry in case we renamed + the directory because of a name conflict. + + * tree.c(scan_directory_tree): Take directory_entry pointer + as second argument so that we can create a backpointer + in the directory structure that points back to the original + dir. + + * mkisofs.c: Fix call to scan_directory_tree to use new calling + sequence. + + * write.c(generate_one_directory): Punt if the last_extent counter + ever exceeds 700Mb/2048. Print name of responsible file, + extent counter, and starting extent. Perhaps we can catch it in + the act. + +Sun Sep 26 20:58:05 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.93. + + * tree.c(scan_directory_tree): Handle symlinks better. Either + leave them as symlinks, or erase any trace that they were a + symlink but do not do it 1/2 way as before. Also, watch for + directory loops created with symlinks. + + * mkisofs.h: Add new flag follow_links. + + * mkisofs.c: Add command line switch "-f" to toggle follow_links. + + * mkisofs.8: Document new switch. + + * tree.c: Add code to handle symlinks using new flag. + + * hash.c: Add add_directory_hash, find_directory_hash functions. + + * mkisofs.h: Add prototypes. + +Sat Sep 25 14:26:31 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.92. + + * mkisofs.c: Make sure path is an actual directory before trying + to scan it. + + * mkisofs.h: Add DECL and FDECL? macros for sparc like systems. + Do proper define of optind and optarg under SVr4. + + * tree.c: Change translation table name from YMTRANS.TBL to TRANS.TBL. + + * mkisofs.c: Neaten up message in extension record when RRIP is + in use. + + * Throughout - change all function declarations so that + traditional C compilers (i.e. sparc) will work. + + * Makefile: Change to use system default C compiler. + + * mkisofs.c: Add some stuff so that this will compile under VMS. + Many things missing for VMS still. + + * iso9660.h: Do not use zero length array in struct definition. + + * tree.c (sort_n_finish): Account for this. + + * Change copyright notice. + + +Wed Aug 25 08:06:51 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.91. + + * mkisofs.h: Only include sys/dir.h for linux. Other systems + will need other things. + + * mkisofs.c, tree.c: Include unistd.h. + + * Makefile: Use OBJS to define list of object files. + +Sun Aug 22 20:55:17 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.9. + + * write.c (iso_7*): Fix so that they work properly on Motorola + systems. + +Fri Aug 20 00:14:36 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.8. + + * rock.c: Do not mask off write permissions from posix file modes. + +Wed Aug 18 09:02:12 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.7. + + * rock.c: Do not write NM field for . and .. (redundant and a + waste of space). + + * mkisofs.c: Take -P and -p options for publisher and preparer id + fields. + + * write.c: Store publisher and preparer id in volume + descriptor. + + * rock.c: Write optional SP field to identify SUSP. Write + optional CE field to point to the extension header. + + * tree.c: Request SP and CE fields be added to root directory. + + * tree.c: Fix bug in name conflict resolution. + + * write.c: Fill in date fields in the colume descriptor. + + * write.c (write_one_file): If the file is large enough, write in + chunks of 16 sectors to improve performance. + + * hash.c (add_hash, find_hash, etc): Do not hash s_entry, instead + store relevant info in hash structure (we free s_entry structs as + we write files, and we need to have access to the hash table the + whole way through. + + * write.c: Add a few statistics about directory sizes, RR sizes, + translation table sizes, etc. + + * tree.c: Use major, not MAJOR. Same for minor. Define S_ISSOCK + and S_ISLNK if not defined. + + * rock.c: Define S_ISLNK if not defined. + + * mkisofs.c: Print out max memory usage. Fix bug in call to getopt. + + * mkisofs.c, Makefile (version_string): Bump to 0.6. + + * tree.c: Simplify the calculation of isorec.len, isorec.name_len + and the calculation of the path table sizes by doing it all at + one point after conflict resolution is done. + + * tree.c: scan_directory_tree is now responsible for generating + the line that goes into the YMTRANS.TBL file. These lines are + collected later on into something that will be dumped to the + file. Correctly handle all of the special file types. + +Mon Aug 16 21:59:47 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.5. + + * mkisofs.c: Add -a option (to force all files to be + transferred). Remove find_file_hash stuff. + + * write.c: Pad length even if Rock Ridge is not in use. + + * hash.c: Rewrite hash_file_* stuff so that it can be used to + easily detect (and look up) filenames that have been accepted + for use in this directory. Used for name collision detection. + + * tree.c (sort_n_finish): If two names collide, generate a unique + one (verified with the hash routines). Change the lower priority + name if there is a difference. + + + +Sat Aug 14 13:18:21 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c, Makefile (version_string): Bump to 0.4. + + * tree.c (load_translation_table): New function - read + YMTRANS.TBL. (scan_directory_tree) Call it. + + * mkisofs.c (iso9660_file_length): Call find_file_hash to see + if translated name is specified. If so, use it. + + * hash.c (name_hash, add_file_hash, find_file_hash, + flush_file_hash): New functions for hashing stuff from + YMTRANS.TBL. + + * mkisofs.h: Add a bunch of prototypes for the new functions. + + * mkisofs.8: Update. + + * mkisofs.c, Makefile (version_string): Bump to 0.3. + + * Makefile: Add version number to tar file in dist target. + + * mkisofs.c: Call finish_cl_pl_entries() after directories have + been generated, and extent numbers assigned. + + * write.c (generate_one_directory): Update s_entry->size for + directories (as well as isorec.size). + + * rock.c: Add code to generate CL, PL, and RE entries. The + extent numbers for the CL and PL entries are NULL, and these + are filled in later once we know where they actually belong. + + * mkisofs.h: Add parent_rec to directory_entry. Used to fix CL/PL + stuff. + + * tree.c (scan_directory_tree): Set flag to generate CL/PL/RE + entries as required, update sizes as well. + +Fri Aug 13 19:49:30 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c (version_string): Bump to 0.2. + + * hash.c: Do not use entries with inode == 0xffffffff or dev == + 0xffff. + + * write.c (write_path_tables): Strip leading directory specifications. + + * mkisofs.h: Add definition for reloc_dir symbol. Add prototype + for sort_n_finish, add third parameter to scan_directory_tree + (for true parent, when directories are relocated). + + * mkisofs.c (main): Modify call to scan_directory_tree. Call + sort_n_finish for reloc_dir. + + * tree.c (sort_n_finish): New function - moved code from + scan_directory_tree. + + * tree.c (generate_reloc_directory): New function. Generate + directory to hold relocated directories. + + * tree.c (scan_directory_tree): Strip leading directories when + generating this_dir->name. If depth is too great, then move + directory to reloc_dir (creating if it does not exist, and leave + a dummy (non-directory) entry in the regular directory so that + we can eventually add the required Rock Ridge record. + + * tree.c (scan_directory_tree): Use s_entry instead of sort_dir, + assign to this_dir->contents sooner. + +Thu Aug 12 22:38:17 1993 Eric Youngdale (eric@kafka) + + * mkisofs.c (usage): Fix syntax. + + * mkisofs.c (main): Add new argument to scan_directory_tree + + * tree.c (scan_directory_tree): If directory is at depth 8 or + more, create rr_moved directory in main directory. + +Mon Jul 26 19:45:47 1993 Eric Youngdale (eric@kafka) + + * mkisofs v 0.1 released. + diff --git a/gnu/usr.bin/mkisofs/Makefile.in b/gnu/usr.bin/mkisofs/Makefile.in new file mode 100644 index 000000000000..724ceb68ead5 --- /dev/null +++ b/gnu/usr.bin/mkisofs/Makefile.in @@ -0,0 +1,51 @@ +#CFLAGS=-g -Wall -c +#CC=gcc + +# +# XCFLAGS is automatically set by Configure. +# +XCFLAGS= +CFLAGS=-g -c $(XCFLAGS) +LDFLAGS= +OBJS=mkisofs.o tree.o write.o hash.o rock.o exclude.o + +World: mkisofs + +Makefile: Makefile.in Configure + ./Configure + echo "Type make again to build mkisofs." + +mkisofs: Makefile $(OBJS) + $(CC) $(LDFLAGS) -o mkisofs $(OBJS) + +install: mkisofs mkisofs.8 + strip mkisofs + cp mkisofs /usr/bin/ + if [ -d /usr/man/man8 ]; then cp mkisofs.8 /usr/man/man8/; fi + +tree.o: tree.c mkisofs.h iso9660.h exclude.h + $(CC) $(CFLAGS) tree.c + +write.o: write.c mkisofs.h iso9660.h + $(CC) $(CFLAGS) write.c + +hash.o: hash.c mkisofs.h + $(CC) $(CFLAGS) hash.c + +rock.o: rock.c mkisofs.h iso9660.h + $(CC) $(CFLAGS) rock.c + +exclude.o: exclude.c exclude.h + $(CC) $(CFLAGS) exclude.c + +mkisofs.o: mkisofs.c iso9660.h mkisofs.h exclude.h + $(CC) $(CFLAGS) mkisofs.c + +clean: + /bin/rm -f *.o core mkisofs *~ #*# + (cd diag/; make clean) + (cd cdwrite/; make clean) + +dist: + tar -cvf - README Configure Makefile.in make.com TODO COPYING ChangeLog *.8 *.c *.h diag cdwrite.old cdwrite-1.5 | gzip > mkisofs-1.04.tar.gz + diff --git a/gnu/usr.bin/mkisofs/README b/gnu/usr.bin/mkisofs/README new file mode 100644 index 000000000000..f2f415f66215 --- /dev/null +++ b/gnu/usr.bin/mkisofs/README @@ -0,0 +1,84 @@ +Note: + There is a feature which can be optionally compiled into +mkisofs that allows you to merge arbitrary directory trees into the +image you are creating. You need to compile with -DADD_FILES for my +changes to take effect. Thanks to Ross Biro biro@yggdrasil.com. + + This program requires a lot of virtual memory to run since it +builds all of the directories in memory. The exact requirements +depend upon a lot of things, but for Rock Ridge discs 12Mb would not +be unreasonable. Without RockRidge and without the translation +tables, the requirements would be considerably less. + + The cdwrite utility is maintained separately from mkisofs by +yggdrasil.com. It is enclosed here as a convenience, since the two programs +are often useful together. + +***************************** +Notes for version 1.2. + + Minor bugfixes here and there. Support for compiled in +defaults for many of the text fields in the volume header are now +present, and there is also support for a file ".mkisofsrc" that can +also read settings for these parameters. + + A short script "Configure" was added to allow us to set up special +compile options that depend upon the system that we are running on. +This should help stamp out the sphaghetti-isms that were starting to grow +up in various places in the code. + + You should get more meaningful error messages if you run out of +memory. + +***************************** +Notes for version 1.1. + + The big news is that SUSP CE entries are now generated for +extremely long filenames and symlink names. This virtually guarantees +that there is no limit (OK, well, about 600Mb) for file name lengths. +I have tested this as well as I can, and it seems to work with linux. +This would only be used very rarely I suspect. + + Also, I believe that support for VMS is done. You must be +careful, because only Stream-LF and FIxed length record files can be +recorded. The rest are rejected with error messages. Perhaps I am +being too severe here. + + There is a bugfix in the sorting of entries on the disc - we +need to stop comparing once we reach the ';' character. + + There are four new options -z -d -D -l -V. Some of these tell +mkisofs to relax some of the iso9660 restrictions, and many systems +apparently do not really seem to mind. Use these with caution. + + Some diagnostic programs to scan disc images are in the diag +directory. These are not as portable as mkisofs, and may have some +bugs. Still they are useful because they can check for bugs that I might +have introduced as I add new features. + +***************************** +Notes for version 1.0. + + In version 1.0, the date fields in the TF fields were fixed - +previously I was storing st_ctime as the file creation time instead of +the file attribute change time. Thanks to Peter van der Veen for +pointing this out. I have one slight concern with this change, +however. The Young Minds software is definitely supplying 3 dates +(creation, modification and access), and I would strongly suspect that +they are incorrectly putting the file attribute change time in the +file creation slot. I would be curious to see how the different RRIP +filesystems treat this. Anyway, this is something to keep in the back +of your mind. + + The symlink handling was not quite correct in 0.99 - this is +now fixed. Only some systems seemed to have been affected by this bug. + + A command line option is now present to allow you to +specifically exclude certain files from the distribution. + + The case where you do not have permissions to read a directory +is now handled better by mkisofs. The directory that cannot be opened +is converted into a zero-length file, and processing continues normally. + + A few portability things have been fixed (hopefully). + diff --git a/gnu/usr.bin/mkisofs/defaults.h b/gnu/usr.bin/mkisofs/defaults.h new file mode 100644 index 000000000000..4e93814d0c4b --- /dev/null +++ b/gnu/usr.bin/mkisofs/defaults.h @@ -0,0 +1,25 @@ +/* + * Header file defaults.h - assorted default values for character strings in + * the volume descriptor. + */ + +#define PREPARER_DEFAULT NULL +#define PUBLISHER_DEFAULT NULL +#define APPID_DEFAULT NULL +#define COPYRIGHT_DEFAULT NULL +#define BIBLIO_DEFAULT NULL +#define ABSTRACT_DEFAULT NULL +#define VOLSET_ID_DEFAULT NULL +#define VOLUME_ID_DEFAULT "CDROM" + +#ifdef __QNX__ +#define SYSTEM_ID_DEFAULT "QNX" +#endif + +#ifdef __osf__ +#define SYSTEM_ID_DEFAULT "OSF" +#endif + +#ifndef SYSTEM_ID_DEFAULT +#define SYSTEM_ID_DEFAULT "LINUX" +#endif diff --git a/gnu/usr.bin/mkisofs/diag/Makefile b/gnu/usr.bin/mkisofs/diag/Makefile new file mode 100644 index 000000000000..e6f3a12f117f --- /dev/null +++ b/gnu/usr.bin/mkisofs/diag/Makefile @@ -0,0 +1,16 @@ +#CC = gcc +CC = cc -traditional + +all: dump isodump isovfy + +isoinfo:isoinfo.c + ${CC} -g -o isoinfo isoinfo.c +dump:dump.c + ${CC} -o dump dump.c +isodump:isodump.c + ${CC} -o isodump isodump.c +isovfy:isovfy.c + ${CC} -o isovfy isovfy.c + +clean: + rm -f dump isodump isovfy isoinfo diff --git a/gnu/usr.bin/mkisofs/diag/isodump.c b/gnu/usr.bin/mkisofs/diag/isodump.c new file mode 100644 index 000000000000..439ee583ff38 --- /dev/null +++ b/gnu/usr.bin/mkisofs/diag/isodump.c @@ -0,0 +1,436 @@ +/* + * File isodump.c - dump iso9660 directory information. + * + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "../config.h" + +#include <stdio.h> +#ifdef USE_TERMIOS +#include <termios.h> +#include <sys/ioctl.h> +#else +#include <termio.h> +#endif +#include <signal.h> + +FILE * infile; +int file_addr; +unsigned char buffer[2048]; +unsigned char search[64]; + +#define PAGE sizeof(buffer) + +#define ISODCL(from, to) (to - from + 1) + + +int +isonum_731 (char * p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + + +int +isonum_733 (unsigned char * p) +{ + return (isonum_731 (p)); +} + +struct iso_primary_descriptor { + unsigned char type [ISODCL ( 1, 1)]; /* 711 */ + unsigned char id [ISODCL ( 2, 6)]; + unsigned char version [ISODCL ( 7, 7)]; /* 711 */ + unsigned char unused1 [ISODCL ( 8, 8)]; + unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */ + unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */ + unsigned char unused2 [ISODCL ( 73, 80)]; + unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ + unsigned char unused3 [ISODCL ( 89, 120)]; + unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */ + unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ + unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */ + unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */ + unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */ + unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ + unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */ + unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ + unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ + unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */ + unsigned char publisher_id [ISODCL (319, 446)]; /* achars */ + unsigned char preparer_id [ISODCL (447, 574)]; /* achars */ + unsigned char application_id [ISODCL (575, 702)]; /* achars */ + unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ + unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ + unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ + unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ + unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ + unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ + unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ + unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */ + unsigned char unused4 [ISODCL (883, 883)]; + unsigned char application_data [ISODCL (884, 1395)]; + unsigned char unused5 [ISODCL (1396, 2048)]; +}; + +struct iso_directory_record { + unsigned char length [ISODCL (1, 1)]; /* 711 */ + unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + unsigned char extent [ISODCL (3, 10)]; /* 733 */ + unsigned char size [ISODCL (11, 18)]; /* 733 */ + unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */ + unsigned char flags [ISODCL (26, 26)]; + unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */ + unsigned char interleave [ISODCL (28, 28)]; /* 711 */ + unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + unsigned char name_len [ISODCL (33, 33)]; /* 711 */ + unsigned char name [1]; +}; + +#ifdef USE_TERMIOS +struct termios savetty; +struct termios newtty; +#else +struct termio savetty; +struct termio newtty; +#endif + +reset_tty(){ +#ifdef USE_TERMIOS + if(tcsetattr(0, TCSANOW, &savetty) == -1) +#else + if(ioctl(0, TCSETAF, &savetty)==-1) +#endif + { + printf("cannot put tty into normal mode\n"); + exit(1); + } +} + +set_tty(){ +#ifdef USE_TERMIOS + if(tcsetattr(0, TCSANOW, &newtty) == -1) +#else + if(ioctl(0, TCSETAF, &newtty)==-1) +#endif + { + printf("cannot put tty into raw mode\n"); + exit(1); + } +} + +/* Come here when we get a suspend signal from the terminal */ + +onsusp () +{ + /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */ + signal(SIGTTOU, SIG_IGN); + reset_tty (); + fflush (stdout); + signal(SIGTTOU, SIG_DFL); + /* Send the TSTP signal to suspend our process group */ + signal(SIGTSTP, SIG_DFL); +/* sigsetmask(0);*/ + kill (0, SIGTSTP); + /* Pause for station break */ + + /* We're back */ + signal (SIGTSTP, onsusp); + set_tty (); +} + + + +crsr2(int row, int col){ + printf("\033[%d;%dH",row,col); +} + +int parse_rr(unsigned char * pnt, int len, int cont_flag) +{ + int slen; + int ncount; + int extent; + int cont_extent, cont_offset, cont_size; + int flag1, flag2; + unsigned char *pnts; + char symlink[1024]; + int goof; +/* printf(" RRlen=%d ", len); */ + + symlink[0] = 0; + + cont_extent = cont_offset = cont_size = 0; + + ncount = 0; + flag1 = flag2 = 0; + while(len >= 4){ + if(ncount) printf(","); + else printf("["); + printf("%c%c", pnt[0], pnt[1]); + if(pnt[3] != 1) { + printf("**BAD RRVERSION"); + return; + }; + ncount++; + if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff; + if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1; + if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2; + if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4; + if(strncmp(pnt, "NM", 2) == 0) flag2 |= 8; + if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16; + if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32; + if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64; + if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128; + + if(strncmp(pnt, "PX", 2) == 0) { + extent = isonum_733(pnt+12); + printf("=%x", extent); + }; + + if(strncmp(pnt, "CE", 2) == 0) { + cont_extent = isonum_733(pnt+4); + cont_offset = isonum_733(pnt+12); + cont_size = isonum_733(pnt+20); + printf("=[%x,%x,%d]", cont_extent, cont_offset, + cont_size); + }; + + if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) { + extent = isonum_733(pnt+4); + printf("=%x", extent); + }; + + if(strncmp(pnt, "SL", 2) == 0) { + int cflag; + + cflag = pnt[4]; + pnts = pnt+5; + slen = pnt[2] - 5; + while(slen >= 1){ + switch(pnts[0] & 0xfe){ + case 0: + strncat(symlink, pnts+2, pnts[1]); + break; + case 2: + strcat (symlink, "."); + break; + case 4: + strcat (symlink, ".."); + break; + case 8: + if((pnts[0] & 1) == 0)strcat (symlink, "/"); + break; + case 16: + strcat(symlink,"/mnt"); + printf("Warning - mount point requested"); + break; + case 32: + strcat(symlink,"kafka"); + printf("Warning - host_name requested"); + break; + default: + printf("Reserved bit setting in symlink", goof++); + break; + }; + if((pnts[0] & 0xfe) && pnts[1] != 0) { + printf("Incorrect length in symlink component"); + }; + if((pnts[0] & 1) == 0) strcat(symlink,"/"); + + slen -= (pnts[1] + 2); + pnts += (pnts[1] + 2); + + }; + if(cflag) printf("+"); + printf("=%s", symlink); + symlink[0] = 0; + }; + + len -= pnt[2]; + pnt += pnt[2]; + if(len <= 3 && cont_extent) { + unsigned char sector[2048]; + lseek(fileno(infile), cont_extent << 11, 0); + read(fileno(infile), sector, sizeof(sector)); + flag2 |= parse_rr(§or[cont_offset], cont_size, 1); + }; + }; + if(ncount) printf("]"); + if (!cont_flag && flag1 != flag2) + printf("Flag %x != %x", flag1, flag2, goof++); + return flag2; +} + +int +dump_rr(struct iso_directory_record * idr) +{ + int len; + unsigned char * pnt; + + len = idr->length[0] & 0xff; + len -= sizeof(struct iso_directory_record); + len += sizeof(idr->name); + len -= idr->name_len[0]; + pnt = (unsigned char *) idr; + pnt += sizeof(struct iso_directory_record); + pnt -= sizeof(idr->name); + pnt += idr->name_len[0]; + if((idr->name_len[0] & 1) == 0){ + pnt++; + len--; + }; + parse_rr(pnt, len, 0); +} + + +showblock(int flag){ + unsigned int k; + int i, j; + int line; + struct iso_directory_record * idr; + lseek(fileno(infile), file_addr, 0); + read(fileno(infile), buffer, sizeof(buffer)); + for(i=0;i<60;i++) printf("\n"); + fflush(stdout); + i = line = 0; + if(flag) { + while(1==1){ + crsr2(line+3,1); + idr = (struct iso_directory_record *) &buffer[i]; + if(idr->length[0] == 0) break; + printf("%3d ", idr->length[0]); + printf("[%2d] ", idr->volume_sequence_number[0]); + printf("%5x ", isonum_733(idr->extent)); + printf("%8d ", isonum_733(idr->size)); + printf ((idr->flags[0] & 2) ? "*" : " "); + if(idr->name_len[0] == 1 && idr->name[0] == 0) + printf(". "); + else if(idr->name_len[0] == 1 && idr->name[0] == 1) + printf(".. "); + else { + for(j=0; j<idr->name_len[0]; j++) printf("%c", idr->name[j]); + for(j=0; j<14 -idr->name_len[0]; j++) printf(" "); + }; + dump_rr(idr); + printf("\n"); + i += buffer[i]; + if (i > 2048 - sizeof(struct iso_directory_record)) break; + line++; + }; + }; + printf("\n"); + printf(" Zone, zone offset: %6x %4.4x ",file_addr>>11, file_addr & 0x7ff); + fflush(stdout); +} + +getbyte() +{ + char c1; + c1 = buffer[file_addr & (PAGE-1)]; + file_addr++; + if ((file_addr & (PAGE-1)) == 0) showblock(0); + return c1; +} + +main(int argc, char * argv[]){ + char c; + char buffer[2048]; + int nbyte; + int i,j; + struct iso_primary_descriptor ipd; + struct iso_directory_record * idr; + + if(argc < 2) return 0; + infile = fopen(argv[1],"rb"); + + file_addr = 16 << 11; + lseek(fileno(infile), file_addr, 0); + read(fileno(infile), &ipd, sizeof(ipd)); + + idr = (struct iso_directory_record *) &ipd.root_directory_record; + + file_addr = isonum_733(idr->extent); + + file_addr = file_addr << 11; + +/* Now setup the keyboard for single character input. */ +#ifdef USE_TERMIOS + if(tcgetattr(0, &savetty) == -1) +#else + if(ioctl(0, TCGETA, &savetty) == -1) +#endif + { + printf("stdin must be a tty\n"); + exit(1); + } + newtty=savetty; + newtty.c_lflag&=~ICANON; + newtty.c_lflag&=~ECHO; + newtty.c_cc[VMIN]=1; + set_tty(); + signal(SIGTSTP, onsusp); + + do{ + if(file_addr < 0) file_addr = 0; + showblock(1); + read (0, &c, 1); + if (c == 'a') file_addr -= PAGE; + if (c == 'b') file_addr += PAGE; + if (c == 'g') { + crsr2(20,1); + printf("Enter new starting block (in hex):"); + scanf("%x",&file_addr); + file_addr = file_addr << 11; + crsr2(20,1); + printf(" "); + }; + if (c == 'f') { + crsr2(20,1); + printf("Enter new search string:"); + fgets(search,sizeof(search),stdin); + while(search[strlen(search)-1] == '\n') search[strlen(search)-1] = 0; + crsr2(20,1); + printf(" "); + }; + if (c == '+') { + while(1==1){ + while(1==1){ + c = getbyte(&file_addr); + if (c == search[0]) break; + }; + for (j=1;j<strlen(search);j++) + if(search[j] != getbyte()) break; + if(j==strlen(search)) break; + }; + file_addr &= ~(PAGE-1); + showblock(1); + }; + if (c == 'q') break; + } while(1==1); + reset_tty(); + fclose(infile); +} + + + + diff --git a/gnu/usr.bin/mkisofs/diag/isoinfo.c b/gnu/usr.bin/mkisofs/diag/isoinfo.c new file mode 100644 index 000000000000..3f3b472f1873 --- /dev/null +++ b/gnu/usr.bin/mkisofs/diag/isoinfo.c @@ -0,0 +1,522 @@ +/* + * File isodump.c - dump iso9660 directory information. + * + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* + * Simple program to dump contents of iso9660 image in more usable format. + * + * Usage: + * To list contents of image (with or without RR): + * isoinfo -l [-R] -i imagefile + * To extract file from image: + * isoinfo -i imagefile -x xtractfile > outfile + * To generate a "find" like list of files: + * isoinfo -f -i imagefile + */ + +#include "../config.h" + +#include <stdio.h> +#include <signal.h> +#include <sys/stat.h> + +#ifdef __svr4__ +#include <stdlib.h> +#else +extern int optind; +extern char *optarg; +/* extern int getopt (int __argc, char **__argv, char *__optstring); */ +#endif + +FILE * infile; +int use_rock = 0; +int do_listing = 0; +int do_find = 0; +char * xtract = 0; + +struct stat fstat_buf; +char name_buf[256]; +char xname[256]; +unsigned char date_buf[9]; + +unsigned char buffer[2048]; + +#define PAGE sizeof(buffer) + +#define ISODCL(from, to) (to - from + 1) + + +int +isonum_731 (char * p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + + +int +isonum_733 (unsigned char * p) +{ + return (isonum_731 (p)); +} + +struct iso_primary_descriptor { + unsigned char type [ISODCL ( 1, 1)]; /* 711 */ + unsigned char id [ISODCL ( 2, 6)]; + unsigned char version [ISODCL ( 7, 7)]; /* 711 */ + unsigned char unused1 [ISODCL ( 8, 8)]; + unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */ + unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */ + unsigned char unused2 [ISODCL ( 73, 80)]; + unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ + unsigned char unused3 [ISODCL ( 89, 120)]; + unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */ + unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ + unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */ + unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */ + unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */ + unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ + unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */ + unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ + unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ + unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */ + unsigned char publisher_id [ISODCL (319, 446)]; /* achars */ + unsigned char preparer_id [ISODCL (447, 574)]; /* achars */ + unsigned char application_id [ISODCL (575, 702)]; /* achars */ + unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ + unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ + unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ + unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ + unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ + unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ + unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ + unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */ + unsigned char unused4 [ISODCL (883, 883)]; + unsigned char application_data [ISODCL (884, 1395)]; + unsigned char unused5 [ISODCL (1396, 2048)]; +}; + +struct iso_directory_record { + unsigned char length [ISODCL (1, 1)]; /* 711 */ + unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + unsigned char extent [ISODCL (3, 10)]; /* 733 */ + unsigned char size [ISODCL (11, 18)]; /* 733 */ + unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */ + unsigned char flags [ISODCL (26, 26)]; + unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */ + unsigned char interleave [ISODCL (28, 28)]; /* 711 */ + unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + unsigned char name_len [ISODCL (33, 33)]; /* 711 */ + unsigned char name [1]; +}; + + +int parse_rr(unsigned char * pnt, int len, int cont_flag) +{ + int slen; + int ncount; + int extent; + int cont_extent, cont_offset, cont_size; + int flag1, flag2; + unsigned char *pnts; + char symlink[1024]; + int goof; + + symlink[0] = 0; + + cont_extent = cont_offset = cont_size = 0; + + ncount = 0; + flag1 = flag2 = 0; + while(len >= 4){ + if(pnt[3] != 1) { + printf("**BAD RRVERSION"); + return; + }; + ncount++; + if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff; + if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1; + if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2; + if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4; + if(strncmp(pnt, "NM", 2) == 0) flag2 |= 8; + if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16; + if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32; + if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64; + if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128; + + if(strncmp(pnt, "PX", 2) == 0) { + fstat_buf.st_mode = isonum_733(pnt+4); + fstat_buf.st_nlink = isonum_733(pnt+12); + fstat_buf.st_uid = isonum_733(pnt+20); + fstat_buf.st_gid = isonum_733(pnt+28); + }; + + if(strncmp(pnt, "NM", 2) == 0) { + strncpy(name_buf, pnt+5, pnt[2] - 5); + name_buf[pnt[2] - 5] = 0; + } + + if(strncmp(pnt, "CE", 2) == 0) { + cont_extent = isonum_733(pnt+4); + cont_offset = isonum_733(pnt+12); + cont_size = isonum_733(pnt+20); + }; + + if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) { + extent = isonum_733(pnt+4); + }; + + if(strncmp(pnt, "SL", 2) == 0) { + int cflag; + + cflag = pnt[4]; + pnts = pnt+5; + slen = pnt[2] - 5; + while(slen >= 1){ + switch(pnts[0] & 0xfe){ + case 0: + strncat(symlink, pnts+2, pnts[1]); + break; + case 2: + strcat (symlink, "."); + break; + case 4: + strcat (symlink, ".."); + break; + case 8: + if((pnts[0] & 1) == 0)strcat (symlink, "/"); + break; + case 16: + strcat(symlink,"/mnt"); + printf("Warning - mount point requested"); + break; + case 32: + strcat(symlink,"kafka"); + printf("Warning - host_name requested"); + break; + default: + printf("Reserved bit setting in symlink", goof++); + break; + }; + if((pnts[0] & 0xfe) && pnts[1] != 0) { + printf("Incorrect length in symlink component"); + }; + if((pnts[0] & 1) == 0) strcat(symlink,"/"); + + slen -= (pnts[1] + 2); + pnts += (pnts[1] + 2); + if(xname[0] == 0) strcpy(xname, "-> "); + strcat(xname, symlink); + }; + symlink[0] = 0; + }; + + len -= pnt[2]; + pnt += pnt[2]; + if(len <= 3 && cont_extent) { + unsigned char sector[2048]; + lseek(fileno(infile), cont_extent << 11, 0); + read(fileno(infile), sector, sizeof(sector)); + flag2 |= parse_rr(§or[cont_offset], cont_size, 1); + }; + }; + return flag2; +} + +int +dump_rr(struct iso_directory_record * idr) +{ + int len; + unsigned char * pnt; + + len = idr->length[0] & 0xff; + len -= sizeof(struct iso_directory_record); + len += sizeof(idr->name); + len -= idr->name_len[0]; + pnt = (unsigned char *) idr; + pnt += sizeof(struct iso_directory_record); + pnt -= sizeof(idr->name); + pnt += idr->name_len[0]; + if((idr->name_len[0] & 1) == 0){ + pnt++; + len--; + }; + parse_rr(pnt, len, 0); +} + +struct todo +{ + struct todo * next; + char * name; + int extent; + int length; +}; + +struct todo * todo_idr = NULL; + +char * months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", + "Aug", "Sep", "Oct", "Nov", "Dec"}; + +dump_stat() +{ + int i; + char outline[80]; + + memset(outline, ' ', sizeof(outline)); + + if(S_ISREG(fstat_buf.st_mode)) + outline[0] = '-'; + else if(S_ISDIR(fstat_buf.st_mode)) + outline[0] = 'd'; + else if(S_ISLNK(fstat_buf.st_mode)) + outline[0] = 'l'; + else if(S_ISCHR(fstat_buf.st_mode)) + outline[0] = 'c'; + else if(S_ISBLK(fstat_buf.st_mode)) + outline[0] = 'b'; + else if(S_ISFIFO(fstat_buf.st_mode)) + outline[0] = 'f'; + else if(S_ISSOCK(fstat_buf.st_mode)) + outline[0] = 's'; + else + outline[0] = '?'; + + memset(outline+1, '-', 9); + if( fstat_buf.st_mode & S_IRUSR ) + outline[1] = 'r'; + if( fstat_buf.st_mode & S_IWUSR ) + outline[2] = 'w'; + if( fstat_buf.st_mode & S_IXUSR ) + outline[3] = 'x'; + + if( fstat_buf.st_mode & S_IRGRP ) + outline[4] = 'r'; + if( fstat_buf.st_mode & S_IWGRP ) + outline[5] = 'w'; + if( fstat_buf.st_mode & S_IXGRP ) + outline[6] = 'x'; + + if( fstat_buf.st_mode & S_IROTH ) + outline[7] = 'r'; + if( fstat_buf.st_mode & S_IWOTH ) + outline[8] = 'w'; + if( fstat_buf.st_mode & S_IXOTH ) + outline[9] = 'x'; + + sprintf(outline+11, "%3d", fstat_buf.st_nlink); + sprintf(outline+15, "%4o", fstat_buf.st_uid); + sprintf(outline+20, "%4o", fstat_buf.st_gid); + sprintf(outline+33, "%8d", fstat_buf.st_size); + + memcpy(outline+42, months[date_buf[1]-1], 3); + sprintf(outline+46, "%2d", date_buf[2]); + sprintf(outline+49, "%4d", date_buf[0]+1900); + + for(i=0; i<54; i++) + if(outline[i] == 0) outline[i] = ' '; + outline[54] = 0; + + printf("%s %s %s\n", outline, name_buf, xname); +} + +extract_file(struct iso_directory_record * idr) +{ + int extent, len, tlen; + unsigned char buff[2048]; + + extent = isonum_733(idr->extent); + len = isonum_733(idr->size); + + while(len > 0) + { + lseek(fileno(infile), extent << 11, 0); + tlen = (len > sizeof(buff) ? sizeof(buff) : len); + read(fileno(infile), buff, tlen); + len -= tlen; + extent++; + write(1, buff, tlen); + } +} + +parse_dir(char * rootname, int extent, int len){ + unsigned int k; + char testname[256]; + struct todo * td; + int i, j; + struct iso_directory_record * idr; + + + if( do_listing) + printf("\nDirectory listing of %s\n", rootname); + + while(len > 0 ) + { + lseek(fileno(infile), extent << 11, 0); + read(fileno(infile), buffer, sizeof(buffer)); + len -= sizeof(buffer); + extent++; + i = 0; + while(1==1){ + idr = (struct iso_directory_record *) &buffer[i]; + if(idr->length[0] == 0) break; + memset(&fstat_buf, 0, sizeof(fstat_buf)); + name_buf[0] = xname[0] = 0; + fstat_buf.st_size = isonum_733(idr->size); + if( idr->flags[0] & 2) + fstat_buf.st_mode |= S_IFDIR; + else + fstat_buf.st_mode |= S_IFREG; + if(idr->name_len[0] == 1 && idr->name[0] == 0) + strcpy(name_buf, "."); + else if(idr->name_len[0] == 1 && idr->name[0] == 1) + strcpy(name_buf, ".."); + else { + strncpy(name_buf, idr->name, idr->name_len[0]); + name_buf[idr->name_len[0]] = 0; + }; + memcpy(date_buf, idr->date, 9); + if(use_rock) dump_rr(idr); + if( (idr->flags[0] & 2) != 0 + && (idr->name_len[0] != 1 + || (idr->name[0] != 0 && idr->name[0] != 1))) + { + /* + * Add this directory to the todo list. + */ + td = todo_idr; + if( td != NULL ) + { + while(td->next != NULL) td = td->next; + td->next = (struct todo *) malloc(sizeof(*td)); + td = td->next; + } + else + { + todo_idr = td = (struct todo *) malloc(sizeof(*td)); + } + td->next = NULL; + td->extent = isonum_733(idr->extent); + td->length = isonum_733(idr->size); + td->name = (char *) malloc(strlen(rootname) + + strlen(name_buf) + 2); + strcpy(td->name, rootname); + strcat(td->name, name_buf); + strcat(td->name, "/"); + } + else + { + strcpy(testname, rootname); + strcat(testname, name_buf); + if(xtract && strcmp(xtract, testname) == 0) + { + extract_file(idr); + } + } + if( do_find + && (idr->name_len[0] != 1 + || (idr->name[0] != 0 && idr->name[0] != 1))) + { + strcpy(testname, rootname); + strcat(testname, name_buf); + printf("%s\n", testname); + } + if(do_listing) + dump_stat(); + i += buffer[i]; + if (i > 2048 - sizeof(struct iso_directory_record)) break; + } + } +} + +usage() +{ + fprintf(stderr, "isoinfo -i filename [-l] [-R] [-x filename] [-f]\n"); +} + +main(int argc, char * argv[]){ + char c; + char buffer[2048]; + int nbyte; + char * filename = NULL; + int i,j; + struct todo * td; + struct iso_primary_descriptor ipd; + struct iso_directory_record * idr; + + if(argc < 2) return 0; + while ((c = getopt(argc, argv, "i:Rlx:f")) != EOF) + switch (c) + { + case 'f': + do_find++; + break; + case 'R': + use_rock++; + break; + case 'l': + do_listing++; + break; + case 'i': + filename = optarg; + break; + case 'x': + xtract = optarg; + break; + default: + usage(); + exit(1); + } + + if( filename == NULL ) + { + fprintf(stderr, "Error - file not specified\n"); + exit(1); + } + + infile = fopen(filename,"rb"); + + if( infile == NULL ) + { + fprintf(stderr,"Unable to open file %s\n", filename); + exit(1); + } + + lseek(fileno(infile), 16<<11, 0); + read(fileno(infile), &ipd, sizeof(ipd)); + + idr = (struct iso_directory_record *) &ipd.root_directory_record; + + parse_dir("/", isonum_733(idr->extent), isonum_733(idr->size)); + td = todo_idr; + while(td) + { + parse_dir(td->name, td->extent, td->length); + td = td->next; + } + + fclose(infile); +} + + + + diff --git a/gnu/usr.bin/mkisofs/diag/isovfy.c b/gnu/usr.bin/mkisofs/diag/isovfy.c new file mode 100644 index 000000000000..d341a34866b3 --- /dev/null +++ b/gnu/usr.bin/mkisofs/diag/isovfy.c @@ -0,0 +1,490 @@ +/* + * File isovfy.c - verify consistency of iso9660 filesystem. + * + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <stdio.h> +#include <signal.h> + +FILE * infile; + +#define PAGE sizeof(buffer) + +#define ISODCL(from, to) (to - from + 1) + +struct iso_primary_descriptor { + unsigned char type [ISODCL ( 1, 1)]; /* 711 */ + unsigned char id [ISODCL ( 2, 6)]; + unsigned char version [ISODCL ( 7, 7)]; /* 711 */ + unsigned char unused1 [ISODCL ( 8, 8)]; + unsigned char system_id [ISODCL ( 9, 40)]; /* aunsigned chars */ + unsigned char volume_id [ISODCL ( 41, 72)]; /* dunsigned chars */ + unsigned char unused2 [ISODCL ( 73, 80)]; + unsigned char volume_space_size [ISODCL ( 81, 88)]; /* 733 */ + unsigned char unused3 [ISODCL ( 89, 120)]; + unsigned char volume_set_size [ISODCL (121, 124)]; /* 723 */ + unsigned char volume_sequence_number [ISODCL (125, 128)]; /* 723 */ + unsigned char logical_block_size [ISODCL (129, 132)]; /* 723 */ + unsigned char path_table_size [ISODCL (133, 140)]; /* 733 */ + unsigned char type_l_path_table [ISODCL (141, 144)]; /* 731 */ + unsigned char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */ + unsigned char type_m_path_table [ISODCL (149, 152)]; /* 732 */ + unsigned char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */ + unsigned char root_directory_record [ISODCL (157, 190)]; /* 9.1 */ + unsigned char volume_set_id [ISODCL (191, 318)]; /* dunsigned chars */ + unsigned char publisher_id [ISODCL (319, 446)]; /* achars */ + unsigned char preparer_id [ISODCL (447, 574)]; /* achars */ + unsigned char application_id [ISODCL (575, 702)]; /* achars */ + unsigned char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */ + unsigned char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */ + unsigned char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */ + unsigned char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */ + unsigned char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */ + unsigned char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */ + unsigned char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */ + unsigned char file_structure_version [ISODCL (882, 882)]; /* 711 */ + unsigned char unused4 [ISODCL (883, 883)]; + unsigned char application_data [ISODCL (884, 1395)]; + unsigned char unused5 [ISODCL (1396, 2048)]; +}; + +struct iso_directory_record { + unsigned char length [ISODCL (1, 1)]; /* 711 */ + unsigned char ext_attr_length [ISODCL (2, 2)]; /* 711 */ + unsigned char extent [ISODCL (3, 10)]; /* 733 */ + unsigned char size [ISODCL (11, 18)]; /* 733 */ + unsigned char date [ISODCL (19, 25)]; /* 7 by 711 */ + unsigned char flags [ISODCL (26, 26)]; + unsigned char file_unit_size [ISODCL (27, 27)]; /* 711 */ + unsigned char interleave [ISODCL (28, 28)]; /* 711 */ + unsigned char volume_sequence_number [ISODCL (29, 32)]; /* 723 */ + unsigned char name_len [ISODCL (33, 33)]; /* 711 */ + unsigned char name [38]; +}; + +int +isonum_721 (char * p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8)); +} + +int +isonum_731 (char * p) +{ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + +int +isonum_722 (char * p) +{ + return ((p[1] & 0xff) + | ((p[0] & 0xff) << 8)); +} + +int +isonum_732 (char * p) +{ + return ((p[3] & 0xff) + | ((p[2] & 0xff) << 8) + | ((p[1] & 0xff) << 16) + | ((p[0] & 0xff) << 24)); +} + +int +isonum_733 (unsigned char * p) +{ + return (isonum_731 (p)); +} + +char lbuffer[1024]; +int iline; +int rr_goof; + + +int +dump_rr(struct iso_directory_record * idr){ + int len; + char * pnt; + + len = idr->length[0] & 0xff; + len -= (sizeof(struct iso_directory_record) - sizeof(idr->name)); + len -= idr->name_len[0]; + pnt = (char *) idr; + pnt += (sizeof(struct iso_directory_record) - sizeof(idr->name)); + pnt += idr->name_len[0]; + + if((idr->name_len[0] & 1) == 0){ + pnt++; + len--; + }; + + rr_goof = 0; + parse_rr(pnt, len, 0); + return rr_goof; +} + +int parse_rr(unsigned char * pnt, int len, int cont_flag) +{ + int slen; + int ncount; + int flag1, flag2; + int extent; + unsigned char *pnts; + int cont_extent, cont_offset, cont_size; + char symlink[1024]; + iline += sprintf(lbuffer+iline," RRlen=%d ", len); + + cont_extent = cont_offset = cont_size = 0; + + symlink[0] = 0; + + ncount = 0; + flag1 = flag2 = 0; + while(len >= 4){ + if(ncount) iline += sprintf(lbuffer+iline,","); + else iline += sprintf(lbuffer+iline,"["); + iline += sprintf(lbuffer+iline,"%c%c", pnt[0], pnt[1]); + + if(pnt[0] < 'A' || pnt[0] > 'Z' || pnt[1] < 'A' || + pnt[1] > 'Z') { + iline += sprintf(lbuffer+iline,"**BAD SUSP %d %d]", + pnt[0], pnt[1], rr_goof++); + return flag2; + }; + + if(pnt[3] != 1) { + iline += sprintf(lbuffer+iline,"**BAD RRVERSION", rr_goof++); + return flag2; + }; + ncount++; + if(pnt[0] == 'R' && pnt[1] == 'R') flag1 = pnt[4] & 0xff; + if(strncmp(pnt, "PX", 2) == 0) flag2 |= 1; + if(strncmp(pnt, "PN", 2) == 0) flag2 |= 2; + if(strncmp(pnt, "SL", 2) == 0) flag2 |= 4; + if(strncmp(pnt, "NM", 2) == 0) flag2 |= 8; + if(strncmp(pnt, "CL", 2) == 0) flag2 |= 16; + if(strncmp(pnt, "PL", 2) == 0) flag2 |= 32; + if(strncmp(pnt, "RE", 2) == 0) flag2 |= 64; + if(strncmp(pnt, "TF", 2) == 0) flag2 |= 128; + + if(strncmp(pnt, "CE", 2) == 0) { + cont_extent = isonum_733(pnt+4); + cont_offset = isonum_733(pnt+12); + cont_size = isonum_733(pnt+20); + iline += sprintf(lbuffer+iline, "=[%x,%x,%d]", + cont_extent, cont_offset, cont_size); + }; + + if(strncmp(pnt, "PL", 2) == 0 || strncmp(pnt, "CL", 2) == 0) { + extent = isonum_733(pnt+4); + iline += sprintf(lbuffer+iline,"=%x", extent); + if(extent == 0) rr_goof++; + }; + if(strncmp(pnt, "SL", 2) == 0) { + pnts = pnt+5; + slen = pnt[2] - 5; + while(slen >= 1){ + switch(pnts[0] & 0xfe){ + case 0: + strncat(symlink, pnts+2, pnts[1]); + break; + case 2: + strcat (symlink, "."); + break; + case 4: + strcat (symlink, ".."); + break; + case 8: + strcat (symlink, "/"); + break; + case 16: + strcat(symlink,"/mnt"); + iline += sprintf(lbuffer+iline,"Warning - mount point requested"); + break; + case 32: + strcat(symlink,"kafka"); + iline += sprintf(lbuffer+iline,"Warning - host_name requested"); + break; + default: + iline += sprintf(lbuffer+iline,"Reserved bit setting in symlink", rr_goof++); + break; + }; + if((pnts[0] & 0xfe) && pnts[1] != 0) { + iline += sprintf(lbuffer+iline,"Incorrect length in symlink component"); + }; + if((pnts[0] & 1) == 0) + strcat(symlink,"/"); + slen -= (pnts[1] + 2); + pnts += (pnts[1] + 2); + + }; + if(symlink[0] != 0) { + iline += sprintf(lbuffer+iline,"=%s", symlink); + symlink[0] = 0; + } + }; + + len -= pnt[2]; + pnt += pnt[2]; + if(len <= 3 && cont_extent) { + unsigned char sector[2048]; + lseek(fileno(infile), cont_extent << 11, 0); + read(fileno(infile), sector, sizeof(sector)); + flag2 |= parse_rr(§or[cont_offset], cont_size, 1); + }; + }; + if(ncount) iline += sprintf(lbuffer+iline,"]"); + if (!cont_flag && flag1 && flag1 != flag2) + iline += sprintf(lbuffer+iline,"Flag %x != %x", flag1, flag2, rr_goof++); + return flag2; +} + + +int dir_count = 0; +int dir_size_count = 0; +int ngoof = 0; + + +check_tree(int file_addr, int file_size, int parent_addr){ + unsigned char buffer[2048]; + unsigned int k; + int rflag; + int i, i1, j, goof; + int extent, size; + int line; + int orig_file_addr, parent_file_addr; + struct iso_directory_record * idr; + + i1 = 0; + + orig_file_addr = file_addr >> 11; /* Actual extent of this directory */ + parent_file_addr = parent_addr >> 11; + + if((dir_count % 100) == 0) printf("[%d %d]\n", dir_count, dir_size_count); +#if 0 + printf("Starting directory %d %d %d\n", file_addr, file_size, parent_addr); +#endif + + dir_count++; + dir_size_count += file_size >> 11; + + if(file_size & 0x3ff) printf("********Directory has unusual size\n"); + + for(k=0; k < (file_size >> 11); k++){ + lseek(fileno(infile), file_addr, 0); + read(fileno(infile), buffer, sizeof(buffer)); + i = 0; + while(1==1){ + goof = iline=0; + idr = (struct iso_directory_record *) &buffer[i]; + if(idr->length[0] == 0) break; + iline += sprintf(&lbuffer[iline],"%3d ", idr->length[0]); + extent = isonum_733(idr->extent); + size = isonum_733(idr->size); + iline += sprintf(&lbuffer[iline],"%5x ", extent); + iline += sprintf(&lbuffer[iline],"%8d ", size); + iline += sprintf (&lbuffer[iline], "%c", (idr->flags[0] & 2) ? '*' : ' '); + + if(idr->name_len[0] > 33 || idr->name_len[0] < 0) + iline += sprintf(&lbuffer[iline],"File name length=(%d)", + idr->name_len[0], goof++); + else if(idr->name_len[0] == 1 && idr->name[0] == 0) { + iline += sprintf(&lbuffer[iline],". "); + rflag = 0; + if(orig_file_addr !=isonum_733(idr->extent)) + iline += sprintf(&lbuffer[iline],"***** Directory has null extent.", goof++); + if(i1) + iline += sprintf(&lbuffer[iline],"***** . not first entry.", rr_goof++); + } else if(idr->name_len[0] == 1 && idr->name[0] == 1) { + iline += sprintf(&lbuffer[iline],".. "); + rflag = 0; + if(parent_file_addr !=isonum_733(idr->extent)) + iline += sprintf(&lbuffer[iline],"***** Directory has null extent.", goof++); + if(i1 != 1) + iline += sprintf(&lbuffer[iline],"***** .. not second entry.", rr_goof++); + + } else { + if(i1 < 2) iline += sprintf(&lbuffer[iline]," Improper sorting.", rr_goof++); + for(j=0; j<idr->name_len[0]; j++) iline += sprintf(&lbuffer[iline],"%c", idr->name[j]); + for(j=0; j<14 -idr->name_len[0]; j++) iline += sprintf(&lbuffer[iline]," "); + rflag = 1; + }; + + if(size && extent == 0) iline += sprintf(&lbuffer[iline],"****Extent==0, size != 0", goof++); +#if 0 + /* This is apparently legal. */ + if(size == 0 && extent) iline += sprintf(&lbuffer[iline],"****Extent!=0, size == 0", goof++); +#endif + + if(idr->flags[0] & 0xfd) + iline += sprintf(&lbuffer[iline],"Flags=(%x) ", idr->flags[0], goof++); + + if(idr->flags[0] & 0xfd) + iline += sprintf(&lbuffer[iline],"Flags=(%x) ", idr->flags[0], goof++); + + if(idr->interleave[0]) + iline += sprintf(&lbuffer[iline],"Interleave=(%d) ", idr->interleave[0], goof++); + + if(idr->file_unit_size[0]) + iline += sprintf(&lbuffer[iline],"File unit size=(%d) ", idr->file_unit_size[0], goof++); + + if(idr->volume_sequence_number[0] != 1) + iline += sprintf(&lbuffer[iline],"Volume sequence number=(%d) ", idr->volume_sequence_number[0], goof++); + + goof += dump_rr(idr); + iline += sprintf(&lbuffer[iline],"\n"); + + + if(goof){ + ngoof++; + lbuffer[iline++] = 0; + printf("%x: %s", orig_file_addr, lbuffer); + }; + + + + if(rflag && (idr->flags[0] & 2)) check_tree((isonum_733(idr->extent)) << 11, + isonum_733(idr->size), + orig_file_addr << 11); + i += buffer[i]; + i1++; + if (i > 2048 - sizeof(struct iso_directory_record)) break; + }; + file_addr += sizeof(buffer); + }; + fflush(stdout); +} + + +/* This function simply dumps the contents of the path tables. No + consistency checking takes place, although this would proably be a good + idea. */ + +struct path_table_info{ + char * name; + unsigned int extent; + unsigned short index; + unsigned short parent; +}; + + +check_path_tables(int typel_extent, int typem_extent, int path_table_size){ + int file_addr; + int count; + int j; + char * pnt; + char * typel, *typem; + + /* Now read in the path tables */ + + typel = (char *) malloc(path_table_size); + lseek(fileno(infile), typel_extent << 11, 0); + read(fileno(infile), typel, path_table_size); + + typem = (char *) malloc(path_table_size); + lseek(fileno(infile), typem_extent << 11, 0); + read(fileno(infile), typem, path_table_size); + + j = path_table_size; + pnt = typel; + count = 1; + while(j){ + int namelen, extent, index; + char name[32]; + namelen = *pnt++; pnt++; + extent = isonum_731(pnt); pnt += 4; + index = isonum_721(pnt); pnt+= 2; + j -= 8+namelen; + memset(name, 0, sizeof(name)); + + strncpy(name, pnt, namelen); + pnt += namelen; + if(j & 1) { j--; pnt++;}; + printf("%4.4d %4.4d %8.8x %s\n",count++, index, extent, name); + }; + + j = path_table_size; + pnt = typem; + count = 1; + while(j){ + int namelen, extent, index; + char name[32]; + namelen = *pnt++; pnt++; + extent = isonum_732(pnt); pnt += 4; + index = isonum_722(pnt); pnt+= 2; + j -= 8+namelen; + memset(name, 0, sizeof(name)); + + strncpy(name, pnt, namelen); + pnt += namelen; + if(j & 1) { j--; pnt++;}; + printf("%4.4d %4.4d %8.8x %s\n", count++, index, extent, name); + }; + +} + +main(int argc, char * argv[]){ + int file_addr, file_size; + char c; + int nbyte; + struct iso_primary_descriptor ipd; + struct iso_directory_record * idr; + int typel_extent, typem_extent; + int path_table_size; + int i,j; + if(argc < 2) return 0; + infile = fopen(argv[1],"rb"); + + + file_addr = 16 << 11; + lseek(fileno(infile), file_addr, 0); + read(fileno(infile), &ipd, sizeof(ipd)); + + idr = (struct iso_directory_record *) &ipd.root_directory_record; + + file_addr = isonum_733(idr->extent); + file_size = isonum_733(idr->size); + + printf("Root at extent %x, %d bytes\n", file_addr, file_size); + file_addr = file_addr << 11; + + check_tree(file_addr, file_size, file_addr); + + typel_extent = isonum_731(ipd.type_l_path_table); + typem_extent = isonum_732(ipd.type_m_path_table); + path_table_size = isonum_733(ipd.path_table_size); + + /* Enable this to get the dump of the path tables */ +#if 0 + check_path_tables(typel_extent, typem_extent, path_table_size); +#endif + + fclose(infile); + + if(!ngoof) printf("No errors found\n"); +} + + + + diff --git a/gnu/usr.bin/mkisofs/exclude.c b/gnu/usr.bin/mkisofs/exclude.c new file mode 100644 index 000000000000..65320796f9c1 --- /dev/null +++ b/gnu/usr.bin/mkisofs/exclude.c @@ -0,0 +1,54 @@ +/* + * 9-Dec-93 R.-D. Marzusch, marzusch@odiehh.hanse.de: + * added 'exclude' option (-x) to specify pathnames NOT to be included in + * CD image. + */ + +#include <stdio.h> +#ifndef VMS +#ifdef HASMALLOC_H +#include <malloc.h> +#else +#include <stdlib.h> +#endif +#endif +#include <string.h> + +/* this allows for 1000 entries to be excluded ... */ +#define MAXEXCL 1000 +static char * excl[MAXEXCL]; + +void exclude(fn) +char * fn; +{ + register int i; + + for (i=0; excl[i] && i<MAXEXCL; i++); + if (i == MAXEXCL) { + fprintf(stderr,"Can't exclude '%s' - too many entries in table\n",fn); + return; + } + + + excl[i] = (char *) malloc(strlen(fn)+1); + if (! excl[i]) { + fprintf(stderr,"Can't allocate memory for excluded filename\n"); + return; + } + + strcpy(excl[i],fn); +} + +int is_excluded(fn) +char * fn; +{ + /* very dumb search method ... */ + register int i; + + for (i=0; excl[i] && i<MAXEXCL; i++) { + if (strcmp(excl[i],fn) == 0) { + return 1; /* found -> excluded filenmae */ + } + } + return 0; /* not found -> not excluded */ +} diff --git a/gnu/usr.bin/mkisofs/mkisofs.8 b/gnu/usr.bin/mkisofs/mkisofs.8 new file mode 100644 index 000000000000..d05909bf537e --- /dev/null +++ b/gnu/usr.bin/mkisofs/mkisofs.8 @@ -0,0 +1,274 @@ +.\" -*- nroff -*- +.TH MKISOFS 8 "January 1995" "Version 1.04" +.SH NAME +mkisofs \- create a iso9660 filesystem with optional Rock Ridge attributes. +.SH SYNOPSIS +.B mkisofs +[ +.B \-R +] +[ +.B \-T +] +[ +.B \-v +] +[ +.B \-z +] +[ +.B \-a +] +[ +.B \-f +] +[ +.B \-d +] +[ +.B \-D +] +[ +.B \-l +] +[ +.B \-L +] +[ +.B \-L +] +[ +.B \-V +] +[ +.B \-V +.I volid +] +[ +.B \-i +.I include-list +] +[ +.B \-p +.I preparer +] +[ +.B \-P +.I publisher +] +[ +.B \-A +.I application_id +] +[ +.B \-x +.I path +] +.B \-o +.I filename +.I path +.SH DESCRIPTION +.B mkisofs +is effectively a pre-mastering program to generate the iso9660 filesystem - it +takes a snapshot of a given directory tree, and generates a binary image which +will correspond to an iso9660 filesystem when written to a block device. +.PP +.B mkisofs +is also capable of generating the System Use Sharing Protocol records specified +by the Rock Ridge Interchange Protocol. This is used to further describe the +files in the iso9660 filesystem to a unix host, and provides information such +as longer filenames, uid/gid, posix permissions, and block and character +devices. +.PP +Each file written to the iso9660 filesystem must have a filename in the 8.3 +format (8 characters, period, 3 characters, all upper case), even if Rock Ridge +is in use. This filename is used on systems that are not able to make use of +the Rock Ridge extensions (such as MS-DOS), and each filename in each directory +must be different from the other filenames in the same directory. +.B mkisofs +generally tries to form correct names by forcing the unix filename to upper +case and truncating as required, but often times this yields unsatisfactory +results when there are cases where the +truncated names are not all unique. +.B mkisofs +assigns weightings to each filename, and if two names that are otherwise the +same are found the name with the lower priority is renamed to have a 3 digit +number as an extension (where the number is guaranteed to be unique). An +example of this would be the files foo.bar and +foo.bar.~1~ - the file foo.bar.~1~ would be written as FOO.000;1 and the file +foo.bar would be written as FOO.BAR;1 +.PP +Note that +.B mkisofs +is not designed to communicate with the writer directly. Most writers +have proprietary command sets which vary from one manufacturer to +another, and you need a specialized tool to actually burn the disk. +The cdwrite utility that comes with mkisofs is capable of communicating +with Phillips drives (newer versions of cdwrite should be available from +Yggdrasil). Most writers come with some version of DOS software +that allows a direct image copy of an iso9660 image to the writer. +.PP +Also you should know that most cd writers are very particular about timing. +Once you start to burn a disc, you cannot let their buffer empty before you +are done, or you will end up with a corrupt disc. Thus it is critical +that you be able to maintain an uninterupted data stream to the writer +for the entire time that the disc is being written. +.PP +.br +.B path +is the path of the directory tree to be copied into the iso9660 filesystem. +.SH OPTIONS +.TP +.I \-a +Include all files on the iso9660 filesystem. Normally files that contain the +characters '~' or '#' will not be included (these are typically backup files +for editors under unix). +.TP +.I \-A application_id +Specifies a text string that will be written into the volume header. +This should describe the application that will be on the disc. There +is space on the disc for 128 characters of information. This parameter can +also be set in the file .mkisofsrc with APPL=id. If specified in both +places, the command line version is used. +.TP +.I \-d +Omit trailing period from files that do not have a period. This violates the +ISO9660 standard, but it happens to work on many systems. Use with caution. +.TP +.I \-D +Do not use deep directory relocation, and instead just pack them in the +way we see them. This violates the ISO9660 standard, but it works on many +systems. Use with caution. +.TP +.I \-f +Follow symbolic links when generating the filesystem. When this option is not +in use, symbolic links will be entered using Rock Ridge if enabled, otherwise +the file will be ignored. +.TP +.I \-i include-list +Use the specified file as a list of files to add to the directory tree. +This is useful for quickly repacking a CD while adding files to it. +The format of this file is path1/file=path2 where path1 is the directory +in the ISO9660 file system where file should appear and path2 is the +where to find the file. +.TP +.I \-l +Allow full 32 character filenames. Normally the ISO9660 filename will be in an +8.3 format which is compatible with MS-DOS, even though the ISO9660 standard +allows filenames of up to 32 characters. If you use this option, the disc may +be difficult to use on a MS-DOS system, but this comes in handy on some other +systems (such as the Amiga). Use with caution. +.TP +.I \-L +Allow filenames to begin with a period. Ususally, a leading dot is +replaced with an underscore in order to maintain MS-DOS compatibility. +.TP +.I \-N +Omit version numbers from ISO9660 file names. This may violate the ISO9660 +standard, but no one really uses the version numbers anyway. Use with caution. +.TP +.I \-o filename +is the name of the file to which the iso9660 filesystem image should be +written. This can be a disk file, a tape drive, or it can correspond directly +to the device name of the optical disc writer. If not specified, stdout is +]used. Note that the output can also be a block special device for a regular +disk drive, in which case the disk partition can be mounted and examined to +ensure that the premastering was done correctly. +.TP +.I \-P publisher_id +Specifies a text string that will be written into the volume header. +This should describe the publisher of the CDROM, usually with a +mailing address and phone number. There is space on the disc for 128 +characters of information. This parameter can also be set in the file +.mkisofsrc with PUBL=. If specified in both places, the command line +version is used. +.TP +.I \-p preparer_id +Specifies a text string that will be written into the volume header. +This should describe the preparer of the CDROM, usually with a mailing +address and phone number. There is space on the disc for 128 +characters of information. This parameter can also be set in the file +.mkisofsrc with PREP=. If specified in both places, the command +line version is used. +.TP +.I \-R +Generate SUSP and RR records using the Rock Ridge protocol to further describe +the files on the iso9660 filesystem. +.TP +.I \-T +Generate a file TRANS.TBL in each directory on the CDROM, which can be used +on non-Rock Ridge capable systems to help establish the correct file names. +There is also information present in the file that indicates the major and +minor numbers for block and character devices, and each symlink has the name of +the link file given. +.TP +.I \-V volid +Specifies the volume ID to be written into the master block. This +parameter can also be set in the file .mkisofsrc with VOLI=id. If +specified in both places, the command line version is used. +.TP +.I \-v +Verbose execution. +.TP +.I \-x path +Exclude +.I path +from being written to CDROM. +.I path +must be the complete pathname that results from concatenating the pathname +given as command line argument and the path relative to this directory. +Multiple paths may be excluded (up to 1000). +Example: + +mkisofs \-o cd \-x /local/dir1 \-x /local/dir2 /local +.TP +.I \-z +Generate special SUSP records for transparently compressed files. This is +only of use and interest for hosts that support transparent decompression. +This is an experimental feature, and no hosts yet support this, but there +are ALPHA patches for linux that can make use of this feature. +.SH CONFIGURATION +.B mkisofs +looks for a file .mkisofsrc, first in the current working directory, and if not +found there then in the directory in which the +.B mkisofs +binary is stored. This file is assumed to contain a series of lines +of the form "TAG=value", and in this way you can specify certain +options. Only the first four characters of the tag are used, and the +case of the tag is not significant. Some fields in the volume header +are not settable on the command line, but can be altered through this +facility. These are the copyright information (COPY), the +bibliographic information (BIBL), the abstract (ABST), the volume set +ID (VOLS) and the system ID (SYSI). +.PP +.B mkisofs +can also be configured at compile time with defaults for many of these fields. +See the file defaults.h. +.SH AUTHOR +.B mkisofs +is not based on the standard mk*fs tools for unix, because we must generate +a complete copy of an existing filesystem on a disk in the iso9660 +filesystem. The name mkisofs is probably a bit of a misnomer, since it +not only creates the filesystem, but it also populates it as well. +.PP +.br +Eric Youngdale <eric@aib.com> wrote both the linux isofs9660 filesystem +and the mkisofs utility, and is currently maintaining them. The copyright for +the mkisofs utility is held by Yggdrasil Computing, Incorporated. +.SH BUGS +Any files that have hard links to files not in the tree being copied to the +iso9660 filessytem will have an incorrect file reference count. +.PP +There may be some other ones. Please, report them to the author. +.SH FUTURE IMPROVEMENTS +Allow specfication of multiple paths on the command line to be included in +iso9660 filesystem. Can be tricky - directory entries in the root directory +need to be properly sorted. +.SH AVAILABILITY +.B mkisofs +is available for anonymous ftp from tsx-11.mit.edu in +/pub/linux/BETA/cdrom/mkisofs and many other mirror sites. With the 1.0 +release, it is no longer considered to be in beta testing. Most of the bugs +that are being discovered now are very minor (and interestingly enough also +seem to be present in the YM software). Reports indicate that people are +gearing up for production runs using version 1.00. diff --git a/gnu/usr.bin/mkisofs/mkisofs.c b/gnu/usr.bin/mkisofs/mkisofs.c new file mode 100644 index 000000000000..f4840aa02b96 --- /dev/null +++ b/gnu/usr.bin/mkisofs/mkisofs.c @@ -0,0 +1,721 @@ +/* + * Program mkisofs.c - generate iso9660 filesystem based upon directory + * tree on hard disk. + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ + +#include "mkisofs.h" + +#ifdef linux +#include <getopt.h> +#endif + +#include "iso9660.h" +#include <ctype.h> + +#ifndef VMS +#include <time.h> +#else +#include <sys/time.h> +#include "vms.h" +#endif + +#include <stdlib.h> +#include <sys/stat.h> + +#ifndef VMS +#include <unistd.h> +#endif + +#include "exclude.h" + +#ifdef __NetBSD__ +#include <sys/time.h> +#include <sys/resource.h> +#endif + +struct directory * root = NULL; + +static char version_string[] = "mkisofs v1.04"; + +FILE * discimage; +unsigned int next_extent = 0; +unsigned int last_extent = 0; +unsigned int path_table_size = 0; +unsigned int path_table[4] = {0,}; +unsigned int path_blocks = 0; +struct iso_directory_record root_record; +static int timezone_offset; +char * extension_record = NULL; +int extension_record_extent = 0; +static int extension_record_size = 0; + +/* These variables are associated with command line options */ +int use_RockRidge = 0; +int verbose = 0; +int all_files = 0; +int follow_links = 0; +int generate_tables = 0; +char * preparer = PREPARER_DEFAULT; +char * publisher = PUBLISHER_DEFAULT; +char * appid = APPID_DEFAULT; +char * copyright = COPYRIGHT_DEFAULT; +char * biblio = BIBLIO_DEFAULT; +char * abstract = ABSTRACT_DEFAULT; +char * volset_id = VOLSET_ID_DEFAULT; +char * volume_id = VOLUME_ID_DEFAULT; +char * system_id = SYSTEM_ID_DEFAULT; + +int omit_period = 0; /* Violates iso9660, but these are a pain */ +int transparent_compression = 0; /* So far only works with linux */ +int omit_version_number = 0; /* May violate iso9660, but noone uses vers*/ +int RR_relocation_depth = 6; /* Violates iso9660, but most systems work */ +int full_iso9660_filenames = 0; /* Used with Amiga. Disc will not work with + DOS */ +int allow_leading_dots = 0; /* DOS cannot read names with leading dots */ + +struct rcopts{ + char * tag; + char ** variable; +}; + +struct rcopts rcopt[] = { + {"PREP", &preparer}, + {"PUBL", &publisher}, + {"APPI", &appid}, + {"COPY", ©right}, + {"BIBL", &biblio}, + {"ABST", &abstract}, + {"VOLS", &volset_id}, + {"VOLI", &volume_id}, + {"SYSI", &system_id}, + {NULL, NULL} +}; + +#ifdef ultrix +char *strdup(s) +char *s;{char *c;if(c=(char *)malloc(strlen(s)+1))strcpy(c,s);return c;} +#endif + +void FDECL1(read_rcfile, char *, appname) +{ + FILE * rcfile; + struct rcopts * rco; + char * pnt, *pnt1; + char linebuffer[256]; + rcfile = fopen(".mkisofsrc","r"); + + if(!rcfile) { + if(strlen(appname)+sizeof(".mkisofsrc") > sizeof(linebuffer)) return; + strcpy(linebuffer, appname); + pnt = strrchr(linebuffer,'/'); + if(!pnt) return; + pnt++; + strcpy(pnt, ".mkisofsrc"); + rcfile = fopen(linebuffer,"r"); + fprintf(stderr, "Using %s.\n", linebuffer); + } else { + fprintf(stderr, "Using ./.mkisofsrc.\n"); + } + + if(!rcfile) return; + + /* OK, we got it. Now read in the lines and parse them */ + while(!feof(rcfile)) + { + fgets(linebuffer, sizeof(linebuffer), rcfile); + pnt = linebuffer; + while(1==1) { + if(*pnt == ' ' || *pnt == '\t' || *pnt == '\n' || *pnt == 0) break; + if(islower(*pnt)) *pnt = toupper(*pnt); + pnt++; + } + /* OK, now find the '=' sign */ + while(*pnt && *pnt != '=' && *pnt != '#') pnt++; + + if(*pnt == '#') continue; /* SKip comment */ + if(*pnt != '=') continue; /* Skip to next line */ + pnt++; /* Skip past '=' sign */ + + while(*pnt == ' ' || *pnt == '\t') pnt++; /* And skip past whitespace */ + + /* Now get rid of trailing newline */ + pnt1 = pnt; + while(*pnt1) { + if(*pnt1 == '\n') *pnt1 = 0; + else + pnt1++; + }; + pnt1 = linebuffer; + while(*pnt1 == ' ' || *pnt1 == '\t') pnt1++; + /* OK, now figure out which option we have */ + for(rco = rcopt; rco->tag; rco++) { + if(strncmp(rco->tag, pnt1, 4) == 0) + { + *rco->variable = strdup(pnt); + break; + }; + } + } + fclose(rcfile); +} + +char * path_table_l = NULL; +char * path_table_m = NULL; +int goof = 0; + +void usage(){ + fprintf(stderr,"Usage:\n"); + fprintf(stderr, +"mkisofs [-o outfile] [-R] [-V volid] [-v] [-a] \ +[-T]\n [-l] [-d] [-V] [-D] [-L] [-p preparer] \ +[-P publisher] [ -A app_id ] [-z] \ +[-x path -x path ...] path\n"); + exit(1); +} + +int get_iso9660_timezone_offset(){ + struct tm gm; + struct tm * pt; + time_t ctime; + int local_min, gmt_min; + + time(&ctime); + pt = gmtime(&ctime); + gm = *pt; + pt = localtime(&ctime); + + if(gm.tm_year < pt->tm_year) + gm.tm_yday = -1; + + if(gm.tm_year > pt->tm_year) + pt->tm_yday = -1; + + gmt_min = gm.tm_min + 60*(gm.tm_hour + 24*gm.tm_yday); + local_min = pt->tm_min + 60*(pt->tm_hour + 24*pt->tm_yday); + return (gmt_min - local_min)/15; +} + + +/* Fill in date in the iso9660 format */ +int FDECL2(iso9660_date,char *, result, time_t, ctime){ + struct tm *local; + local = localtime(&ctime); + result[0] = local->tm_year; + result[1] = local->tm_mon + 1; + result[2] = local->tm_mday; + result[3] = local->tm_hour; + result[4] = local->tm_min; + result[5] = local->tm_sec; + result[6] = timezone_offset; + return 0; +} + +int FDECL3(iso9660_file_length,const char*, name, struct directory_entry *, sresult, + int, dirflag){ + int seen_dot = 0; + int seen_semic = 0; + char * result; + int priority = 32767; + int tildes = 0; + int ignore = 0; + int extra = 0; + int current_length = 0; + int chars_after_dot = 0; + int chars_before_dot = 0; + const char * pnt; + result = sresult->isorec.name; + + if(strcmp(name,".") == 0){ + if(result) *result = 0; + return 1; + }; + + if(strcmp(name,"..") == 0){ + if(result) { + *result++ = 1; + *result++ = 0; + } + return 1; + }; + + pnt = name; + while(*pnt){ +#ifdef VMS + if(strcmp(pnt,".DIR;1") == 0) break; +#endif + if(*pnt == '#') {priority = 1; pnt++; continue; }; + if(*pnt == '~') {priority = 1; tildes++; pnt++; continue;}; + if(*pnt == ';') {seen_semic = 1; *result++ = *pnt++; continue; }; + if(ignore) {pnt++; continue;}; + if(seen_semic){ + if(*pnt >= '0' && *pnt <= '9') *result++ = *pnt; + extra++; + pnt++; + continue; + }; + if(full_iso9660_filenames) { + /* Here we allow a more relaxed syntax. */ + if(*pnt == '.') { + if (seen_dot) {ignore++; continue;} + seen_dot++; + } + if(current_length < 30) *result++ = (islower(*pnt) ? toupper(*pnt) : *pnt); + } else { /* Dos style filenames */ + if(*pnt == '.') { + if (!chars_before_dot && !allow_leading_dots) { + /* DOS can't read files with dot first */ + chars_before_dot++; + if (result) *result++ = '_'; /* Substitute underscore */ + } else { + if (seen_dot) {ignore++; continue;} + if(result) *result++ = '.'; + seen_dot++; + } + } else if (seen_dot) { + if(chars_after_dot < 3) { + chars_after_dot++; + if(result) *result++ = (islower(*pnt) ? toupper(*pnt) : *pnt); + } + } else { + if(chars_before_dot < 8) { + chars_before_dot++; + if(result) *result++ = (islower(*pnt) ? toupper(*pnt) : *pnt); + }; + }; + }; + current_length++; + pnt++; + }; + + if(tildes == 2){ + int prio1 = 0; + pnt = name; + while (*pnt && *pnt != '~') pnt++; + if (*pnt) pnt++; + while(*pnt && *pnt != '~'){ + prio1 = 10*prio1 + *pnt - '0'; + pnt++; + }; + priority = prio1; + }; + + if (!dirflag){ + if (!seen_dot && !omit_period) { + if (result) *result++ = '.'; + extra++; + }; + if(!omit_version_number && !seen_semic) { + if(result){ + *result++ = ';'; + *result++ = '1'; + }; + extra += 2; + } + }; + + if(result) *result++ = 0; + sresult->priority = priority; + return chars_before_dot + chars_after_dot + seen_dot + extra; +} + +#ifdef ADD_FILES + +struct file_adds *root_file_adds = NULL; + +void +FDECL2(add_one_file, char *, addpath, char *, path ) +{ + char *cp; + char *name; + struct file_adds *f; + struct file_adds *tmp; + + f = root_file_adds; + tmp = NULL; + + name = rindex (addpath, PATH_SEPARATOR); + if (name == NULL) { + name = addpath; + } else { + name++; + } + + cp = strtok (addpath, SPATH_SEPARATOR); + + while (cp != NULL && strcmp (name, cp)) { + if (f == NULL) { + root_file_adds = e_malloc (sizeof *root_file_adds); + f=root_file_adds; + f->name = NULL; + f->child = NULL; + f->next = NULL; + f->add_count = 0; + f->adds = NULL; + f->used = 0; + } + if (f->child) { + for (tmp = f->child; tmp->next != NULL; tmp =tmp->next) { + if (strcmp (tmp->name, cp) == 0) { + f = tmp; + goto next; + } + } + if (strcmp (tmp->name, cp) == 0) { + f=tmp; + goto next; + } + /* add a new node. */ + tmp->next = e_malloc (sizeof (*tmp->next)); + f=tmp->next; + f->name = strdup (cp); + f->child = NULL; + f->next = NULL; + f->add_count = 0; + f->adds = NULL; + f->used = 0; + } else { + /* no children. */ + f->child = e_malloc (sizeof (*f->child)); + f = f->child; + f->name = strdup (cp); + f->child = NULL; + f->next = NULL; + f->add_count = 0; + f->adds = NULL; + f->used = 0; + + } + next: + cp = strtok (NULL, SPATH_SEPARATOR); + } + /* Now f if non-null points to where we should add things */ + if (f == NULL) { + root_file_adds = e_malloc (sizeof *root_file_adds); + f=root_file_adds; + f->name = NULL; + f->child = NULL; + f->next = NULL; + f->add_count = 0; + f->adds = NULL; + } + + /* Now f really points to where we should add this name. */ + f->add_count++; + f->adds = realloc (f->adds, sizeof (*f->adds)*f->add_count); + f->adds[f->add_count-1].path = strdup (path); + f->adds[f->add_count-1].name = strdup (name); +} + +void +FDECL3(add_file_list, int, argc, char **,argv, int, ind) +{ + char *ptr; + char *dup_arg; + + while (ind < argc) { + dup_arg = strdup (argv[ind]); + ptr = index (dup_arg,'='); + if (ptr == NULL) { + free (dup_arg); + return; + } + *ptr = 0; + ptr++; + add_one_file (dup_arg, ptr); + free (dup_arg); + ind++; + } +} +void +FDECL1(add_file, char *, filename) +{ + char buff[1024]; + FILE *f; + char *ptr; + char *p2; + int count=0; + + if (strcmp (filename, "-") == 0) { + f = stdin; + } else { + f = fopen (filename, "r"); + if (f == NULL) { + perror ("fopen"); + exit (1); + } + } + while (fgets (buff, 1024, f)) { + count++; + ptr = buff; + while (isspace (*ptr)) ptr++; + if (*ptr==0) continue; + if (*ptr=='#') continue; + + if (ptr[strlen(ptr)-1]== '\n') ptr[strlen(ptr)-1]=0; + p2 = index (ptr, '='); + if (p2 == NULL) { + fprintf (stderr, "Error in line %d: %s\n", count, buff); + exit (1); + } + *p2 = 0; + p2++; + add_one_file (ptr, p2); + } + if (f != stdin) fclose (f); +} + +#endif + +int FDECL2(main, int, argc, char **, argv){ + char * outfile; + struct directory_entry de; + unsigned int mem_start; + struct stat statbuf; + char * scan_tree; + int c; +#ifdef ADD_FILES + char *add_file_file = NULL; +#endif + + if (argc < 2) + usage(); + + /* Get the defaults from the .mkisofsrc file */ + read_rcfile(argv[0]); + + outfile = NULL; + while ((c = getopt(argc, argv, "i:o:V:RfvaTp:P:x:dDlLNzA:")) != EOF) + switch (c) + { + case 'p': + preparer = optarg; + if(strlen(preparer) > 128) { + fprintf(stderr,"Preparer string too long\n"); + exit(1); + }; + break; + case 'P': + publisher = optarg; + if(strlen(publisher) > 128) { + fprintf(stderr,"Publisher string too long\n"); + exit(1); + }; + break; + case 'A': + appid = optarg; + if(strlen(appid) > 128) { + fprintf(stderr,"Application-id string too long\n"); + exit(1); + }; + break; + case 'd': + omit_period++; + break; + case 'D': + RR_relocation_depth = 32767; + break; + case 'l': + full_iso9660_filenames++; + break; + case 'L': + allow_leading_dots++; + break; + case 'N': + omit_version_number++; + break; + case 'o': + outfile = optarg; + break; + case 'f': + follow_links++; + break; + case 'R': + use_RockRidge++; + break; + case 'V': + volume_id = optarg; + break; + case 'v': + verbose++; + break; + case 'a': + all_files++; + break; + case 'T': + generate_tables++; + break; + case 'z': +#ifdef VMS + fprintf(stderr,"Transparent compression not supported with VMS\n"); + exit(1); +#else + transparent_compression++; +#endif + break; + case 'x': + exclude(optarg); + break; + case 'i': +#ifdef ADD_FILES + add_file_file = optarg; + break; +#endif + default: + usage(); + exit(1); + } +#ifdef __NetBSD__ + { + int resource; + struct rlimit rlp; + if (getrlimit(RLIMIT_DATA,&rlp) == -1) + perror("Warning: getrlimit"); + else { + rlp.rlim_cur=33554432; + if (setrlimit(RLIMIT_DATA,&rlp) == -1) + perror("Warning: setrlimit"); + } + } +#endif + mem_start = (unsigned int) sbrk(0); + + if(verbose) fprintf(stderr,"%s\n", version_string); + /* Now find the timezone offset */ + + timezone_offset = get_iso9660_timezone_offset(); + + /* The first step is to scan the directory tree, and take some notes */ + + scan_tree = argv[optind]; + +#ifdef ADD_FILES + if (add_file_file) { + add_file(add_file_file); + } + add_file_list (argc, argv, optind+1); +#endif + + if(!scan_tree){ + usage(); + exit(1); + }; + +#ifndef VMS + if(scan_tree[strlen(scan_tree)-1] != '/') { + scan_tree = (char *) e_malloc(strlen(argv[optind])+2); + strcpy(scan_tree, argv[optind]); + strcat(scan_tree, "/"); + }; +#endif + + if(use_RockRidge){ +#if 1 + extension_record = generate_rr_extension_record("RRIP_1991A", + "THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS", + "PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.", &extension_record_size); +#else + extension_record = generate_rr_extension_record("IEEE_P1282", + "THE IEEE P1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS", + "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, PISCATAWAY, NJ, USA FOR THE P1282 SPECIFICATION.", &extension_record_size); +#endif + }; + + stat(argv[optind], &statbuf); + add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); + + de.filedir = root; /* We need this to bootstrap */ + scan_directory_tree(argv[optind], &de); + root->self = root->contents; /* Fix this up so that the path tables get done right */ + + if(reloc_dir) sort_n_finish(reloc_dir); + + if (goof) exit(1); + + if (outfile){ + discimage = fopen(outfile, "w"); + if (!discimage){ + fprintf(stderr,"Unable to open disc image file\n"); + exit(1); + + }; + } else + discimage = stdout; + + /* Now assign addresses on the disc for the path table. */ + + path_blocks = (path_table_size + (SECTOR_SIZE - 1)) >> 11; + if (path_blocks & 1) path_blocks++; + path_table[0] = 0x14; + path_table[1] = path_table[0] + path_blocks; + path_table[2] = path_table[1] + path_blocks; + path_table[3] = path_table[2] + path_blocks; + + last_extent = path_table[3] + path_blocks; /* The next free block */ + + /* The next step is to go through the directory tree and assign extent + numbers for all of the directories */ + + assign_directory_addresses(root); + + if(extension_record) { + struct directory_entry * s_entry; + extension_record_extent = last_extent++; + s_entry = root->contents; + set_733(s_entry->rr_attributes + s_entry->rr_attr_size - 24, + extension_record_extent); + set_733(s_entry->rr_attributes + s_entry->rr_attr_size - 8, + extension_record_size); + }; + + if (use_RockRidge && reloc_dir) + finish_cl_pl_entries(); + + /* Now we generate the path tables that are used by DOS to improve directory + access times. */ + generate_path_tables(); + + /* Generate root record for volume descriptor. */ + generate_root_record(); + + dump_tree(root); + + iso_write(discimage); + + fprintf(stderr,"Max brk space used %x\n", + ((unsigned int)sbrk(0)) - mem_start); + fprintf(stderr,"%d extents written (%d Mb)\n", last_extent, last_extent >> 9); +#ifdef VMS + return 1; +#else + return 0; +#endif +} + +void *e_malloc(size_t size) +{ +void* pt; + if((pt=malloc(size))==NULL) { + printf("Not enougth memory\n"); + exit (1); + } +return pt; +} diff --git a/gnu/usr.bin/mkisofs/mkisofs.h b/gnu/usr.bin/mkisofs/mkisofs.h new file mode 100644 index 000000000000..53d14b9a2679 --- /dev/null +++ b/gnu/usr.bin/mkisofs/mkisofs.h @@ -0,0 +1,263 @@ +/* + * Header file mkisofs.h - assorted structure definitions and typecasts. + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ + +#include <stdio.h> + +/* This symbol is used to indicate that we do not have things like + symlinks, devices, and so forth available. Just files and dirs */ + +#ifdef VMS +#define NON_UNIXFS +#endif + +#ifdef DJGPP +#define NON_UNIXFS +#endif + +#ifdef VMS +#include <sys/dir.h> +#define dirent direct +#else +#include <dirent.h> +#endif + +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef linux +#include <sys/dir.h> +#endif + +#ifdef ultrix +extern char *strdup(); +#endif + +#ifdef __STDC__ +#define DECL(NAME,ARGS) NAME ARGS +#define FDECL1(NAME,TYPE0, ARG0) \ + NAME(TYPE0 ARG0) +#define FDECL2(NAME,TYPE0, ARG0,TYPE1, ARG1) \ + NAME(TYPE0 ARG0, TYPE1 ARG1) +#define FDECL3(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2) \ + NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2) +#define FDECL4(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3) \ + NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3) +#define FDECL5(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4) \ + NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3, TYPE4 ARG4) +#define FDECL6(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4, TYPE5, ARG5) \ + NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3, TYPE4 ARG4, TYPE5 ARG5) +#else +#define DECL(NAME,ARGS) NAME() +#define FDECL1(NAME,TYPE0, ARG0) NAME(ARG0) TYPE0 ARG0; +#define FDECL2(NAME,TYPE0, ARG0,TYPE1, ARG1) NAME(ARG0, ARG1) TYPE0 ARG0; TYPE1 ARG1; +#define FDECL3(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2) \ + NAME(ARG0, ARG1, ARG2) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; +#define FDECL4(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3) \ + NAME(ARG0, ARG1, ARG2, ARG3, ARG4) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3; +#define FDECL5(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4) \ + NAME(ARG0, ARG1, ARG2, ARG3, ARG4) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3; TYPE4 ARG4; +#define FDECL6(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4, TYPE5, ARG5) \ + NAME(ARG0, ARG1, ARG2, ARG3, ARG4, ARG5) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3; TYPE4 ARG4; TYPE5 ARG5; +#define const +#endif + + +#ifdef __svr4__ +#include <stdlib.h> +#else +extern int optind; +extern char *optarg; +/* extern int getopt (int __argc, char **__argv, char *__optstring); */ +#endif + +#include "iso9660.h" +#include "defaults.h" + +struct directory_entry{ + struct directory_entry * next; + struct iso_directory_record isorec; + unsigned int starting_block; + unsigned int size; + unsigned int priority; + char * name; + char * table; + char * whole_name; + struct directory * filedir; + struct directory_entry * parent_rec; + unsigned int flags; + ino_t inode; /* Used in the hash table */ + dev_t dev; /* Used in the hash table */ + unsigned char * rr_attributes; + unsigned int rr_attr_size; + unsigned int total_rr_attr_size; +}; + +struct file_hash{ + struct file_hash * next; + ino_t inode; /* Used in the hash table */ + dev_t dev; /* Used in the hash table */ + unsigned int starting_block; + unsigned int size; +}; + +struct directory{ + struct directory * next; /* Next directory at same level as this one */ + struct directory * subdir; /* First subdirectory in this directory */ + struct directory * parent; + struct directory_entry * contents; + struct directory_entry * self; + char * whole_name; /* Entire path */ + char * de_name; /* Entire path */ + unsigned int ce_bytes; /* Number of bytes of CE entries reqd for this dir */ + unsigned int depth; + unsigned int size; + unsigned int extent; + unsigned short path_index; +}; + +struct deferred{ + struct deferred * next; + unsigned int starting_block; + char * name; + struct directory * filedir; + unsigned int flags; +}; + +#ifdef ADD_FILES +struct file_adds { + char *name; + struct file_adds *child; + struct file_adds *next; + int add_count; + int used; + struct dirent de; + struct { + char *path; + char *name; + } *adds; +}; +extern struct file_adds *root_file_adds; + +#endif + +extern void DECL(sort_n_finish,(struct directory *)); +extern int goof; +extern struct directory * root; +extern struct directory * reloc_dir; +extern unsigned int next_extent; +extern unsigned int last_extent; +extern unsigned int path_table_size; +extern unsigned int path_table[4]; +extern unsigned int path_blocks; +extern char * path_table_l; +extern char * path_table_m; +extern struct iso_directory_record root_record; + +extern int use_RockRidge; +extern int follow_links; +extern int verbose; +extern int all_files; +extern int generate_tables; +extern int omit_period; +extern int omit_version_number; +extern int transparent_compression; +extern int RR_relocation_depth; +extern int full_iso9660_filenames; + +extern int DECL(scan_directory_tree,(char * path, struct directory_entry * self)); +extern void DECL(dump_tree,(struct directory * node)); +extern void DECL(assign_directory_addresses,(struct directory * root)); + +extern int DECL(iso9660_file_length,(const char* name, + struct directory_entry * sresult, int flag)); +extern int DECL(iso_write,(FILE * outfile)); +extern void generate_path_tables(); +extern void DECL(generate_iso9660_directories,(struct directory *, FILE*)); +extern void DECL(generate_one_directory,(struct directory *, FILE*)); +extern void generate_root_record(); +extern int DECL(iso9660_date,(char *, time_t)); +extern void DECL(add_hash,(struct directory_entry *)); +extern struct file_hash * DECL(find_hash,(dev_t, ino_t)); +extern void DECL(add_directory_hash,(dev_t, ino_t)); +extern struct file_hash * DECL(find_directory_hash,(dev_t, ino_t)); +extern void flush_file_hash(); +extern int DECL(delete_file_hash,(struct directory_entry *)); +extern struct directory_entry * DECL(find_file_hash,(char *)); +extern void DECL(add_file_hash,(struct directory_entry *)); +extern void finish_cl_pl_entries(); +extern int DECL(get_733,(char *)); + +extern void DECL(set_723,(char *, unsigned int)); +extern void DECL(set_733,(char *, unsigned int)); +extern void DECL(sort_directory,(struct directory_entry **)); +extern int DECL(generate_rock_ridge_attributes,(char *, char *, + struct directory_entry *, + struct stat *, struct stat *, + int deep_flag)); +extern char * DECL(generate_rr_extension_record,(char * id, char * descriptor, + char * source, int * size)); + +extern char * extension_record; +extern int extension_record_extent; +extern int n_data_extents; + +/* These are a few goodies that can be specified on the command line, and are + filled into the root record */ + +extern char * preparer; +extern char * publisher; +extern char * copyright; +extern char * biblio; +extern char * abstract; +extern char * appid; +extern char * volset_id; +extern char * system_id; +extern char * volume_id; + +extern void * DECL(e_malloc,(size_t)); + + +#define SECTOR_SIZE (2048) +#define ROUND_UP(X) ((X + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1)) + +#define NEED_RE 1 +#define NEED_PL 2 +#define NEED_CL 4 +#define NEED_CE 8 +#define NEED_SP 16 + +#define TABLE_INODE (sizeof(ino_t) >= 4 ? 0x7ffffffe : 0x7ffe) +#define UNCACHED_INODE (sizeof(ino_t) >= 4 ? 0x7fffffff : 0x7fff) +#define UNCACHED_DEVICE (sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff) + +#ifdef VMS +#define STAT_INODE(X) (X.st_ino[0]) +#define PATH_SEPARATOR ']' +#define SPATH_SEPARATOR "" +#else +#define STAT_INODE(X) (X.st_ino) +#define PATH_SEPARATOR '/' +#define SPATH_SEPARATOR "/" +#endif + diff --git a/gnu/usr.bin/mkisofs/rock.c b/gnu/usr.bin/mkisofs/rock.c new file mode 100644 index 000000000000..591fda5818be --- /dev/null +++ b/gnu/usr.bin/mkisofs/rock.c @@ -0,0 +1,530 @@ +/* + * File rock.c - generate RRIP records for iso9660 filesystems. + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <stdlib.h> + +#ifndef VMS +#if defined(HASSYSMACROS) && !defined(HASMKDEV) +#include <sys/sysmacros.h> +#endif +#include <unistd.h> +#endif +#ifdef HASMKDEV +#include <sys/types.h> +#include <sys/mkdev.h> +#endif + +#include "mkisofs.h" +#include "iso9660.h" +#include <string.h> + +#ifdef NON_UNIXFS +#define S_ISLNK(m) (0) +#else +#ifndef S_ISLNK +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#endif +#endif + +#define SU_VERSION 1 + +#define SL_ROOT 8 +#define SL_PARENT 4 +#define SL_CURRENT 2 +#define SL_CONTINUE 1 + +#define CE_SIZE 28 +#define CL_SIZE 12 +#define ER_SIZE 8 +#define NM_SIZE 5 +#define PL_SIZE 12 +#define PN_SIZE 20 +#define PX_SIZE 36 +#define RE_SIZE 4 +#define SL_SIZE 20 +#define ZZ_SIZE 15 +#ifdef __QNX__ +#define TF_SIZE (5 + 4 * 7) +#else +#define TF_SIZE (5 + 3 * 7) +#endif + +/* If we need to store this number of bytes, make sure we + do not box ourselves in so that we do not have room for + a CE entry for the continuation record */ + +#define MAYBE_ADD_CE_ENTRY(BYTES) \ + (BYTES + CE_SIZE + currlen + (ipnt - recstart) > reclimit ? 1 : 0) + +/* + * Buffer to build RR attributes + */ + +static unsigned char Rock[16384]; +static unsigned char symlink_buff[256]; +static int ipnt = 0; +static int recstart = 0; +static int currlen = 0; +static int mainrec = 0; +static int reclimit; + +static add_CE_entry(){ + if(recstart) + set_733((char*)Rock + recstart - 8, ipnt + 28 - recstart); + Rock[ipnt++] ='C'; + Rock[ipnt++] ='E'; + Rock[ipnt++] = CE_SIZE; + Rock[ipnt++] = SU_VERSION; + set_733((char*)Rock + ipnt, 0); + ipnt += 8; + set_733((char*)Rock + ipnt, 0); + ipnt += 8; + set_733((char*)Rock + ipnt, 0); + ipnt += 8; + recstart = ipnt; + currlen = 0; + if(!mainrec) mainrec = ipnt; + reclimit = SECTOR_SIZE - 8; /* Limit to one sector */ +} + +#ifdef __STDC__ +int generate_rock_ridge_attributes (char * whole_name, char * name, + struct directory_entry * s_entry, + struct stat * statbuf, + struct stat * lstatbuf, + int deep_opt) +#else +int generate_rock_ridge_attributes (whole_name, name, + s_entry, + statbuf, + lstatbuf, + deep_opt) +char * whole_name; char * name; struct directory_entry * s_entry; +struct stat * statbuf, *lstatbuf; +int deep_opt; +#endif +{ + int flagpos, flagval; + int need_ce; + + statbuf = statbuf; /* this shuts up unreferenced compiler warnings */ + mainrec = recstart = ipnt = 0; + reclimit = 0xf8; + + /* Obtain the amount of space that is currently used for the directory + record. Assume max for name, since name conflicts may cause us + to rename the file later on */ + currlen = sizeof(s_entry->isorec); + + /* Identify that we are using the SUSP protocol */ + if(deep_opt & NEED_SP){ + Rock[ipnt++] ='S'; + Rock[ipnt++] ='P'; + Rock[ipnt++] = 7; + Rock[ipnt++] = SU_VERSION; + Rock[ipnt++] = 0xbe; + Rock[ipnt++] = 0xef; + Rock[ipnt++] = 0; + }; + + /* First build the posix name field */ + Rock[ipnt++] ='R'; + Rock[ipnt++] ='R'; + Rock[ipnt++] = 5; + Rock[ipnt++] = SU_VERSION; + flagpos = ipnt; + flagval = 0; + Rock[ipnt++] = 0; /* We go back and fix this later */ + + if(strcmp(name,".") && strcmp(name,"..")){ + char * npnt; + int remain, use; + + remain = strlen(name); + npnt = name; + + while(remain){ + use = remain; + need_ce = 0; + /* Can we fit this SUSP and a CE entry? */ + if(use + currlen + CE_SIZE + (ipnt - recstart) > reclimit) { + use = reclimit - currlen - CE_SIZE - (ipnt - recstart); + need_ce++; + } + + /* Only room for 256 per SUSP field */ + if(use > 0xf8) use = 0xf8; + + /* First build the posix name field */ + Rock[ipnt++] ='N'; + Rock[ipnt++] ='M'; + Rock[ipnt++] = NM_SIZE + use; + Rock[ipnt++] = SU_VERSION; + Rock[ipnt++] = (remain != use ? 1 : 0); + flagval |= (1<<3); + strncpy((char *)&Rock[ipnt], npnt, use); + npnt += use; + ipnt += use; + remain -= use; + if(remain && need_ce) add_CE_entry(); + }; + }; + + /* + * Add the posix modes + */ + if(MAYBE_ADD_CE_ENTRY(PX_SIZE)) add_CE_entry(); + Rock[ipnt++] ='P'; + Rock[ipnt++] ='X'; + Rock[ipnt++] = PX_SIZE; + Rock[ipnt++] = SU_VERSION; + flagval |= (1<<0); + set_733((char*)Rock + ipnt, lstatbuf->st_mode); + ipnt += 8; + set_733((char*)Rock + ipnt, lstatbuf->st_nlink); + ipnt += 8; + set_733((char*)Rock + ipnt, lstatbuf->st_uid); + ipnt += 8; + set_733((char*)Rock + ipnt, lstatbuf->st_gid); + ipnt += 8; + + /* + * Check for special devices + */ +#ifndef NON_UNIXFS + if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) { + if(MAYBE_ADD_CE_ENTRY(PN_SIZE)) add_CE_entry(); + Rock[ipnt++] ='P'; + Rock[ipnt++] ='N'; + Rock[ipnt++] = PN_SIZE; + Rock[ipnt++] = SU_VERSION; + flagval |= (1<<1); + if(sizeof(dev_t) <= 4) { + set_733((char*)Rock + ipnt, 0); + ipnt += 8; + set_733((char*)Rock + ipnt, lstatbuf->st_rdev); + ipnt += 8; + } + else { +#ifdef ultrix + set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 16) >> 16); +#else + set_733((char*)Rock + ipnt, lstatbuf->st_rdev >> 32); +#endif + ipnt += 8; + set_733((char*)Rock + ipnt, lstatbuf->st_rdev); + ipnt += 8; + } + }; +#endif + /* + * Check for and symbolic links. VMS does not have these. + */ + if (S_ISLNK(lstatbuf->st_mode)){ + int lenpos, lenval, j0, j1; + int cflag, nchar; + unsigned char * cpnt, *cpnt1; + nchar = readlink(whole_name, symlink_buff, sizeof(symlink_buff)); + symlink_buff[nchar] = 0; + set_733(s_entry->isorec.size, 0); + cpnt = &symlink_buff[0]; + flagval |= (1<<2); + + while(nchar){ + if(MAYBE_ADD_CE_ENTRY(SL_SIZE)) add_CE_entry(); + Rock[ipnt++] ='S'; + Rock[ipnt++] ='L'; + lenpos = ipnt; + Rock[ipnt++] = SL_SIZE; + Rock[ipnt++] = SU_VERSION; + Rock[ipnt++] = 0; /* Flags */ + lenval = 5; + while(*cpnt){ + cpnt1 = (unsigned char *) strchr((char *) cpnt, '/'); + if(cpnt1) { + nchar--; + *cpnt1 = 0; + }; + + /* We treat certain components in a special way. */ + if(cpnt[0] == '.' && cpnt[1] == '.' && cpnt[2] == 0){ + if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry(); + Rock[ipnt++] = SL_PARENT; + Rock[ipnt++] = 0; /* length is zero */ + lenval += 2; + nchar -= 2; + } else if(cpnt[0] == '.' && cpnt[1] == 0){ + if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry(); + Rock[ipnt++] = SL_CURRENT; + Rock[ipnt++] = 0; /* length is zero */ + lenval += 2; + nchar -= 1; + } else if(cpnt[0] == 0){ + if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry(); + Rock[ipnt++] = (cpnt == &symlink_buff[0] ? SL_ROOT : 0); + Rock[ipnt++] = 0; /* length is zero */ + lenval += 2; + } else { + /* If we do not have enough room for a component, start + a new continuations segment now */ + if(MAYBE_ADD_CE_ENTRY(6)) { + add_CE_entry(); + if(cpnt1){ + *cpnt1 = '/'; + cpnt1 = NULL; /* A kluge so that we can restart properly */ + } + break; + } + j0 = strlen((char *) cpnt); + while(j0) { + j1 = j0; + if(j1 > 0xf8) j1 = 0xf8; + need_ce = 0; + if(j1 + currlen + CE_SIZE + (ipnt - recstart) > reclimit) { + j1 = reclimit - currlen - CE_SIZE - (ipnt - recstart); + need_ce++; + } + Rock[ipnt++] = (j1 != j0 ? SL_CONTINUE : 0); + Rock[ipnt++] = j1; + strncpy((char *) Rock + ipnt, (char *) cpnt, j1); + ipnt += j1; + lenval += j1 + 2; + cpnt += j1; + nchar -= j1; /* Number we processed this time */ + j0 -= j1; + if(need_ce) { + add_CE_entry(); + if(cpnt1) { + *cpnt1 = '/'; + cpnt1 = NULL; /* A kluge so that we can restart properly */ + } + break; + } + } + }; + if(cpnt1) { + cpnt = cpnt1 + 1; + } else + break; + }; + Rock[lenpos] = lenval; + if(nchar) Rock[lenpos + 2] = SL_CONTINUE; /* We need another SL entry */ + } /* while nchar */ + } /* Is a symbolic link */ + /* + * Add in the Rock Ridge TF time field + */ + if(MAYBE_ADD_CE_ENTRY(TF_SIZE)) add_CE_entry(); + Rock[ipnt++] ='T'; + Rock[ipnt++] ='F'; + Rock[ipnt++] = TF_SIZE; + Rock[ipnt++] = SU_VERSION; +#ifdef __QNX__ + Rock[ipnt++] = 0x0f; +#else + Rock[ipnt++] = 0x0e; +#endif + flagval |= (1<<7); +#ifdef __QNX__ + iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ftime); + ipnt += 7; +#endif + iso9660_date((char *) &Rock[ipnt], lstatbuf->st_mtime); + ipnt += 7; + iso9660_date((char *) &Rock[ipnt], lstatbuf->st_atime); + ipnt += 7; + iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ctime); + ipnt += 7; + + /* + * Add in the Rock Ridge RE time field + */ + if(deep_opt & NEED_RE){ + if(MAYBE_ADD_CE_ENTRY(RE_SIZE)) add_CE_entry(); + Rock[ipnt++] ='R'; + Rock[ipnt++] ='E'; + Rock[ipnt++] = RE_SIZE; + Rock[ipnt++] = SU_VERSION; + flagval |= (1<<6); + }; + /* + * Add in the Rock Ridge PL record, if required. + */ + if(deep_opt & NEED_PL){ + if(MAYBE_ADD_CE_ENTRY(PL_SIZE)) add_CE_entry(); + Rock[ipnt++] ='P'; + Rock[ipnt++] ='L'; + Rock[ipnt++] = PL_SIZE; + Rock[ipnt++] = SU_VERSION; + set_733((char*)Rock + ipnt, 0); + ipnt += 8; + flagval |= (1<<5); + }; + + /* + * Add in the Rock Ridge CL field, if required. + */ + if(deep_opt & NEED_CL){ + if(MAYBE_ADD_CE_ENTRY(CL_SIZE)) add_CE_entry(); + Rock[ipnt++] ='C'; + Rock[ipnt++] ='L'; + Rock[ipnt++] = CL_SIZE; + Rock[ipnt++] = SU_VERSION; + set_733((char*)Rock + ipnt, 0); + ipnt += 8; + flagval |= (1<<4); + }; + +#ifndef VMS + /* If transparent compression was requested, fill in the correct + field for this file */ + if(transparent_compression && + S_ISREG(lstatbuf->st_mode) && + strlen(name) > 3 && + strcmp(name + strlen(name) - 3,".gZ") == 0){ + FILE * zipfile; + char * checkname; + unsigned int file_size; + unsigned char header[8]; + int OK_flag; + + /* First open file and verify that the correct algorithm was used */ + file_size = 0; + OK_flag = 1; + + zipfile = fopen(whole_name, "r"); + fread(header, 1, sizeof(header), zipfile); + + /* Check some magic numbers from gzip. */ + if(header[0] != 0x1f || header[1] != 0x8b || header[2] != 8) OK_flag = 0; + /* Make sure file was blocksized. */ + if((header[3] & 0x40 == 0)) OK_flag = 0; + /* OK, now go to the end of the file and get some more info */ + if(OK_flag){ + int status; + status = (long)lseek(fileno(zipfile), (off_t)(-8), SEEK_END); + if(status == -1) OK_flag = 0; + } + if(OK_flag){ + if(read(fileno(zipfile), (char*)header, sizeof(header)) != sizeof(header)) + OK_flag = 0; + else { + int blocksize; + blocksize = (header[3] << 8) | header[2]; + file_size = ((unsigned int)header[7] << 24) | + ((unsigned int)header[6] << 16) | + ((unsigned int)header[5] << 8) | header[4]; +#if 0 + fprintf(stderr,"Blocksize = %d %d\n", blocksize, file_size); +#endif + if(blocksize != SECTOR_SIZE) OK_flag = 0; + } + } + fclose(zipfile); + + checkname = strdup(whole_name); + checkname[strlen(whole_name)-3] = 0; + zipfile = fopen(checkname, "r"); + if(zipfile) { + OK_flag = 0; + fprintf(stderr,"Unable to insert transparent compressed file - name conflict\n"); + fclose(zipfile); + } + + free(checkname); + + if(OK_flag){ + if(MAYBE_ADD_CE_ENTRY(ZZ_SIZE)) add_CE_entry(); + Rock[ipnt++] ='Z'; + Rock[ipnt++] ='Z'; + Rock[ipnt++] = ZZ_SIZE; + Rock[ipnt++] = SU_VERSION; + Rock[ipnt++] = 'g'; /* Identify compression technique used */ + Rock[ipnt++] = 'z'; + Rock[ipnt++] = 3; + set_733((char*)Rock + ipnt, file_size); /* Real file size */ + ipnt += 8; + }; + } +#endif + /* + * Add in the Rock Ridge CE field, if required. We use this for the + * extension record that is stored in the root directory. + */ + if(deep_opt & NEED_CE) add_CE_entry(); + /* + * Done filling in all of the fields. Now copy it back to a buffer for the + * file in question. + */ + + /* Now copy this back to the buffer for the file */ + Rock[flagpos] = flagval; + + /* If there was a CE, fill in the size field */ + if(recstart) + set_733((char*)Rock + recstart - 8, ipnt - recstart); + + s_entry->rr_attributes = (unsigned char *) e_malloc(ipnt); + s_entry->total_rr_attr_size = ipnt; + s_entry->rr_attr_size = (mainrec ? mainrec : ipnt); + memcpy(s_entry->rr_attributes, Rock, ipnt); + return ipnt; +} + +/* Guaranteed to return a single sector with the relevant info */ + +char * FDECL4(generate_rr_extension_record, char *, id, char *, descriptor, + char *, source, int *, size){ + int ipnt = 0; + char * pnt; + int len_id, len_des, len_src; + + len_id = strlen(id); + len_des = strlen(descriptor); + len_src = strlen(source); + Rock[ipnt++] ='E'; + Rock[ipnt++] ='R'; + Rock[ipnt++] = ER_SIZE + len_id + len_des + len_src; + Rock[ipnt++] = 1; + Rock[ipnt++] = len_id; + Rock[ipnt++] = len_des; + Rock[ipnt++] = len_src; + Rock[ipnt++] = 1; + + memcpy(Rock + ipnt, id, len_id); + ipnt += len_id; + + memcpy(Rock + ipnt, descriptor, len_des); + ipnt += len_des; + + memcpy(Rock + ipnt, source, len_src); + ipnt += len_src; + + if(ipnt > SECTOR_SIZE) { + fprintf(stderr,"Extension record too long\n"); + exit(1); + }; + pnt = (char *) e_malloc(SECTOR_SIZE); + memset(pnt, 0, SECTOR_SIZE); + memcpy(pnt, Rock, ipnt); + *size = ipnt; + return pnt; +} diff --git a/gnu/usr.bin/mkisofs/tree.c b/gnu/usr.bin/mkisofs/tree.c new file mode 100644 index 000000000000..076f2252a51a --- /dev/null +++ b/gnu/usr.bin/mkisofs/tree.c @@ -0,0 +1,1012 @@ +/* + * File tree.c - scan directory tree and build memory structures for iso9660 + * filesystem + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */ + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <errno.h> + +#ifndef VMS +#if defined(HASSYSMACROS) && !defined(HASMKDEV) +#include <sys/sysmacros.h> +#endif +#include <unistd.h> +#ifdef HASMKDEV +#include <sys/types.h> +#include <sys/mkdev.h> +#endif +#else +#include <sys/file.h> +#include <vms/fabdef.h> +#include "vms.h" +extern char * strdup(const char *); +#endif + +#include "mkisofs.h" +#include "iso9660.h" + +#include <sys/stat.h> + +#include "exclude.h" + +#ifdef NON_UNIXFS +#define S_ISLNK(m) (0) +#define S_ISSOCK(m) (0) +#define S_ISFIFO(m) (0) +#else +#ifndef S_ISLNK +#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) +#endif +#ifndef S_ISSOCK +#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) +#endif +#endif + +#ifdef __svr4__ +extern char * strdup(const char *); +#endif + +static unsigned char symlink_buff[256]; + +extern int verbose; + +struct stat fstatbuf = {0,}; /* We use this for the artificial entries we create */ + +struct stat root_statbuf = {0, }; /* Stat buffer for root directory */ + +struct directory * reloc_dir = NULL; + + +void FDECL1(sort_n_finish, struct directory *, this_dir) +{ + struct directory_entry *s_entry, *s_entry1; + time_t current_time; + struct directory_entry * table; + int count; + int new_reclen; + char * c; + int tablesize = 0; + char newname[34], rootname[34]; + + /* Here we can take the opportunity to toss duplicate entries from the + directory. */ + + table = NULL; + + if(fstatbuf.st_ctime == 0){ + time (¤t_time); + fstatbuf.st_uid = 0; + fstatbuf.st_gid = 0; + fstatbuf.st_ctime = current_time; + fstatbuf.st_mtime = current_time; + fstatbuf.st_atime = current_time; + }; + + flush_file_hash(); + s_entry = this_dir->contents; + while(s_entry){ + + /* First assume no conflict, and handle this case */ + + if(!(s_entry1 = find_file_hash(s_entry->isorec.name))){ + add_file_hash(s_entry); + s_entry = s_entry->next; + continue; + }; + + if(s_entry1 == s_entry){ + fprintf(stderr,"Fatal goof\n"); + exit(1); + }; + /* OK, handle the conflicts. Try substitute names until we come + up with a winner */ + strcpy(rootname, s_entry->isorec.name); + if(full_iso9660_filenames) { + if(strlen(rootname) > 27) rootname[27] = 0; + } + c = strchr(rootname, '.'); + if (c) *c = 0; + count = 0; + while(count < 1000){ + sprintf(newname,"%s.%3.3d%s", rootname, count, + (s_entry->isorec.flags[0] == 2 || + omit_version_number ? "" : ";1")); + +#ifdef VMS + /* Sigh. VAXCRTL seems to be broken here */ + { int ijk = 0; + while(newname[ijk]) { + if(newname[ijk] == ' ') newname[ijk] = '0'; + ijk++; + }; + } +#endif + + if(!find_file_hash(newname)) break; + count++; + }; + if(count >= 1000){ + fprintf(stderr,"Unable to generate unique name for file %s\n", s_entry->name); + exit(1); + }; + + /* OK, now we have a good replacement name. Now decide which one + of these two beasts should get the name changed */ + + if(s_entry->priority < s_entry1->priority) { + fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname, this_dir->whole_name, SPATH_SEPARATOR, s_entry->name, s_entry1->name); + s_entry->isorec.name_len[0] = strlen(newname); + new_reclen = sizeof(struct iso_directory_record) - + sizeof(s_entry->isorec.name) + + strlen(newname); + if(use_RockRidge) { + if (new_reclen & 1) new_reclen++; /* Pad to an even byte */ + new_reclen += s_entry->rr_attr_size; + }; + if (new_reclen & 1) new_reclen++; /* Pad to an even byte */ + s_entry->isorec.length[0] = new_reclen; + strcpy(s_entry->isorec.name, newname); + } else { + delete_file_hash(s_entry1); + fprintf(stderr,"Using %s for %s%s%s (%s)\n", newname, this_dir->whole_name, SPATH_SEPARATOR, s_entry1->name, s_entry->name); + s_entry1->isorec.name_len[0] = strlen(newname); + new_reclen = sizeof(struct iso_directory_record) - + sizeof(s_entry1->isorec.name) + + strlen(newname); + if(use_RockRidge) { + if (new_reclen & 1) new_reclen++; /* Pad to an even byte */ + new_reclen += s_entry1->rr_attr_size; + }; + if (new_reclen & 1) new_reclen++; /* Pad to an even byte */ + s_entry1->isorec.length[0] = new_reclen; + strcpy(s_entry1->isorec.name, newname); + add_file_hash(s_entry1); + }; + add_file_hash(s_entry); + s_entry = s_entry->next; + }; + + if(generate_tables && !find_file_hash("TRANS.TBL") && (reloc_dir != this_dir)){ + /* First we need to figure out how big this table is */ + for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){ + if(strcmp(s_entry->name, ".") == 0 || + strcmp(s_entry->name, "..") == 0) continue; + if(s_entry->table) tablesize += 35 + strlen(s_entry->table); + }; + table = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memset(table, 0, sizeof(struct directory_entry)); + table->table = NULL; + table->next = this_dir->contents; + this_dir->contents = table; + + table->filedir = root; + table->isorec.flags[0] = 0; + table->priority = 32768; + iso9660_date(table->isorec.date, fstatbuf.st_ctime); + table->inode = TABLE_INODE; + table->dev = (dev_t) UNCACHED_DEVICE; + set_723(table->isorec.volume_sequence_number, 1); + set_733(table->isorec.size, tablesize); + table->size = tablesize; + table->filedir = this_dir; + table->name = strdup("<translation table>"); + table->table = (char *) e_malloc(ROUND_UP(tablesize)); + memset(table->table, 0, ROUND_UP(tablesize)); + iso9660_file_length ("TRANS.TBL", table, 1); + + if(use_RockRidge){ + fstatbuf.st_mode = 0444 | S_IFREG; + fstatbuf.st_nlink = 1; + generate_rock_ridge_attributes("", + "TRANS.TBL", table, + &fstatbuf, &fstatbuf, 0); + }; + }; + + for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){ + new_reclen = strlen(s_entry->isorec.name); + + if(s_entry->isorec.flags[0] == 2){ + if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) { + path_table_size += new_reclen + sizeof(struct iso_path_table) - 1; + if (new_reclen & 1) path_table_size++; + } else { + new_reclen = 1; + if (this_dir == root && strlen(s_entry->name) == 1) + path_table_size += sizeof(struct iso_path_table); + } + }; + if(path_table_size & 1) path_table_size++; /* For odd lengths we pad */ + s_entry->isorec.name_len[0] = new_reclen; + + new_reclen += + sizeof(struct iso_directory_record) - + sizeof(s_entry->isorec.name); + + if (new_reclen & 1) + new_reclen++; + if(use_RockRidge){ + new_reclen += s_entry->rr_attr_size; + + if (new_reclen & 1) + new_reclen++; + }; + if(new_reclen > 0xff) { + fprintf(stderr,"Fatal error - RR overflow for file %s\n", + s_entry->name); + exit(1); + }; + s_entry->isorec.length[0] = new_reclen; + }; + + sort_directory(&this_dir->contents); + + if(table){ + char buffer[1024]; + count = 0; + for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next){ + if(s_entry == table) continue; + if(!s_entry->table) continue; + if(strcmp(s_entry->name, ".") == 0 || + strcmp(s_entry->name, "..") == 0) continue; + + sprintf(buffer,"%c %-34s%s",s_entry->table[0], + s_entry->isorec.name, s_entry->table+1); + memcpy(table->table + count, buffer, strlen(buffer)); + count += strlen(buffer); + free(s_entry->table); + s_entry->table = NULL; + }; + if(count != tablesize) { + fprintf(stderr,"Translation table size mismatch %d %d\n", + count, tablesize); + exit(1); + }; + }; + + /* Now go through the directory and figure out how large this one will be. + Do not split a directory entry across a sector boundary */ + + s_entry = this_dir->contents; + this_dir->ce_bytes = 0; + while(s_entry){ + new_reclen = s_entry->isorec.length[0]; + if ((this_dir->size & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE) + this_dir->size = (this_dir->size + (SECTOR_SIZE - 1)) & + ~(SECTOR_SIZE - 1); + this_dir->size += new_reclen; + + /* See if continuation entries were used on disc */ + if(use_RockRidge && + s_entry->rr_attr_size != s_entry->total_rr_attr_size) { + unsigned char * pnt; + int len; + int nbytes; + + pnt = s_entry->rr_attributes; + len = s_entry->total_rr_attr_size; + + /* We make sure that each continuation entry record is not + split across sectors, but each file could in theory have more + than one CE, so we scan through and figure out what we need. */ + + while(len > 3){ + if(pnt[0] == 'C' && pnt[1] == 'E') { + nbytes = get_733(pnt+20); + + if((this_dir->ce_bytes & (SECTOR_SIZE - 1)) + nbytes >= + SECTOR_SIZE) this_dir->ce_bytes = + ROUND_UP(this_dir->ce_bytes); + /* Now store the block in the ce buffer */ + this_dir->ce_bytes += nbytes; + if(this_dir->ce_bytes & 1) this_dir->ce_bytes++; + }; + len -= pnt[2]; + pnt += pnt[2]; + } + } + s_entry = s_entry->next; + } +} + +static void generate_reloc_directory() +{ + int new_reclen; + time_t current_time; + struct directory_entry *s_entry; + + /* Create an entry for our internal tree */ + time (¤t_time); + reloc_dir = (struct directory *) + e_malloc(sizeof(struct directory)); + memset(reloc_dir, 0, sizeof(struct directory)); + reloc_dir->parent = root; + reloc_dir->next = root->subdir; + root->subdir = reloc_dir; + reloc_dir->depth = 1; + reloc_dir->whole_name = strdup("./rr_moved"); + reloc_dir->de_name = strdup("rr_moved"); + reloc_dir->extent = 0; + + new_reclen = strlen(reloc_dir->de_name); + + /* Now create an actual directory entry */ + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memset(s_entry, 0, sizeof(struct directory_entry)); + s_entry->next = root->contents; + reloc_dir->self = s_entry; + + root->contents = s_entry; + root->contents->name = strdup(reloc_dir->de_name); + root->contents->filedir = root; + root->contents->isorec.flags[0] = 2; + root->contents->priority = 32768; + iso9660_date(root->contents->isorec.date, current_time); + root->contents->inode = UNCACHED_INODE; + root->contents->dev = (dev_t) UNCACHED_DEVICE; + set_723(root->contents->isorec.volume_sequence_number, 1); + iso9660_file_length (reloc_dir->de_name, root->contents, 1); + + if(use_RockRidge){ + fstatbuf.st_mode = 0555 | S_IFDIR; + fstatbuf.st_nlink = 2; + generate_rock_ridge_attributes("", + "rr_moved", s_entry, + &fstatbuf, &fstatbuf, 0); + }; + + /* Now create the . and .. entries in rr_moved */ + /* Now create an actual directory entry */ + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memcpy(s_entry, root->contents, + sizeof(struct directory_entry)); + s_entry->name = strdup("."); + iso9660_file_length (".", s_entry, 1); + + s_entry->filedir = reloc_dir; + reloc_dir->contents = s_entry; + + if(use_RockRidge){ + fstatbuf.st_mode = 0555 | S_IFDIR; + fstatbuf.st_nlink = 2; + generate_rock_ridge_attributes("", + ".", s_entry, + &fstatbuf, &fstatbuf, 0); + }; + + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memcpy(s_entry, root->contents, + sizeof(struct directory_entry)); + s_entry->name = strdup(".."); + iso9660_file_length ("..", s_entry, 1); + s_entry->filedir = root; + reloc_dir->contents->next = s_entry; + reloc_dir->contents->next->next = NULL; + if(use_RockRidge){ + fstatbuf.st_mode = 0555 | S_IFDIR; + fstatbuf.st_nlink = 2; + generate_rock_ridge_attributes("", + "..", s_entry, + &root_statbuf, &root_statbuf, 0); + }; +} + +static void FDECL1(increment_nlink, struct directory_entry *, s_entry){ + unsigned char * pnt; + int len, nlink; + + pnt = s_entry->rr_attributes; + len = s_entry->total_rr_attr_size; + while(len){ + if(pnt[0] == 'P' && pnt[1] == 'X') { + nlink = get_733(pnt+12); + set_733(pnt+12, nlink+1); + break; + }; + len -= pnt[2]; + pnt += pnt[2]; + }; +} + +void finish_cl_pl_entries(){ + struct directory_entry *s_entry, *s_entry1; + struct directory * d_entry; + + s_entry = reloc_dir->contents; + s_entry = s_entry->next->next; /* Skip past . and .. */ + for(; s_entry; s_entry = s_entry->next){ + d_entry = reloc_dir->subdir; + while(d_entry){ + if(d_entry->self == s_entry) break; + d_entry = d_entry->next; + }; + if(!d_entry){ + fprintf(stderr,"Unable to locate directory parent\n"); + exit(1); + }; + + /* First fix the PL pointer in the directory in the rr_reloc dir */ + s_entry1 = d_entry->contents->next; + set_733(s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8, + s_entry->filedir->extent); + + /* Now fix the CL pointer */ + s_entry1 = s_entry->parent_rec; + + set_733(s_entry1->rr_attributes + s_entry1->total_rr_attr_size - 8, + d_entry->extent); + + s_entry->filedir = reloc_dir; /* Now we can fix this */ + } + /* Next we need to modify the NLINK terms in the assorted root directory records + to account for the presence of the RR_MOVED directory */ + + increment_nlink(root->self); + increment_nlink(root->self->next); + d_entry = root->subdir; + while(d_entry){ + increment_nlink(d_entry->contents->next); + d_entry = d_entry->next; + }; +} + +#ifdef ADD_FILES +/* This function looks up additions. */ +char * +FDECL3(look_up_addition,char **, newpath, char *,path, struct dirent **,de) { + char *dup_path; + char *cp; + struct file_adds *f; + struct file_adds *tmp; + + f=root_file_adds; + if (!f) return NULL; + + /* I don't trust strtok */ + dup_path = strdup (path); + + cp = strtok (dup_path, SPATH_SEPARATOR); + while (cp != NULL) { + for (tmp = f->child; tmp != NULL; tmp=tmp->next) { + if (strcmp (tmp->name, cp) == 0) break; + } + if (tmp == NULL) { + /* no match */ + free (dup_path); + return (NULL); + } + f = tmp; + cp = strtok(NULL, SPATH_SEPARATOR); + } + free (dup_path); + + /* looks like we found something. */ + if (tmp->used >= tmp->add_count) return (NULL); + + *newpath = tmp->adds[tmp->used].path; + tmp->used++; + *de = &(tmp->de); + return (tmp->adds[tmp->used-1].name); + +} + +/* This function lets us add files from outside the standard file tree. + It is useful if we want to duplicate a cd, but add/replace things. + We should note that the real path will be used for exclusions. */ + +struct dirent * +FDECL3(readdir_add_files, char **, pathp, char *,path, DIR *, dir){ + struct dirent *de; + + char *addpath; + char *name; + + de = readdir (dir); + if (de) { + return (de); + } + + name=look_up_addition (&addpath, path, &de); + + if (!name) { + return; + } + + *pathp=addpath; + + /* Now we must create the directory entry. */ + /* fortuneately only the name seems to matter. */ + /* + de->d_ino = -1; + de->d_off = 0; + de->d_reclen = strlen (name); + */ + strncpy (de->d_name, name, NAME_MAX); + de->d_name[NAME_MAX]=0; + return (de); + +} +#else +struct dirent * +FDECL3(readdir_add_files, char **, pathp, char *,path, DIR *, dir){ + return (readdir (dir)); +} +#endif +/* + * This function scans the directory tree, looking for files, and it makes + * note of everything that is found. We also begin to construct the ISO9660 + * directory entries, so that we can determine how large each directory is. + */ + +int +FDECL2(scan_directory_tree,char *, path, struct directory_entry *, de){ + DIR * current_dir; + char whole_path[1024]; + struct dirent * d_entry; + struct directory_entry *s_entry, *s_entry1; + struct directory * this_dir, *next_brother, *parent; + struct stat statbuf, lstatbuf; + int status, dflag; + char * cpnt; + int new_reclen; + int deep_flag; + char *old_path; + + current_dir = opendir(path); + d_entry = NULL; + + /* Apparently NFS sometimes allows you to open the directory, but + then refuses to allow you to read the contents. Allow for this */ + + old_path = path; + + if(current_dir) d_entry = readdir_add_files(&path, old_path, current_dir); + + if(!current_dir || !d_entry) { + fprintf(stderr,"Unable to open directory %s\n", path); + de->isorec.flags[0] &= ~2; /* Mark as not a directory */ + if(current_dir) closedir(current_dir); + return 0; + }; + + parent = de->filedir; + /* Set up the struct for the current directory, and insert it into the + tree */ + +#ifdef VMS + vms_path_fixup(path); +#endif + + this_dir = (struct directory *) e_malloc(sizeof(struct directory)); + this_dir->next = NULL; + new_reclen = 0; + this_dir->subdir = NULL; + this_dir->self = de; + this_dir->contents = NULL; + this_dir->whole_name = strdup(path); + cpnt = strrchr(path, PATH_SEPARATOR); + if(cpnt) + cpnt++; + else + cpnt = path; + this_dir->de_name = strdup(cpnt); + this_dir->size = 0; + this_dir->extent = 0; + + if(!parent || parent == root){ + if (!root) { + root = this_dir; /* First time through for root directory only */ + root->depth = 0; + root->parent = root; + } else { + this_dir->depth = 1; + if(!root->subdir) + root->subdir = this_dir; + else { + next_brother = root->subdir; + while(next_brother->next) next_brother = next_brother->next; + next_brother->next = this_dir; + }; + this_dir->parent = parent; + }; + } else { + /* Come through here for normal traversal of tree */ +#ifdef DEBUG + fprintf(stderr,"%s(%d) ", path, this_dir->depth); +#endif + if(parent->depth > RR_relocation_depth) { + fprintf(stderr,"Directories too deep %s\n", path); + exit(1); + }; + + this_dir->parent = parent; + this_dir->depth = parent->depth + 1; + + if(!parent->subdir) + parent->subdir = this_dir; + else { + next_brother = parent->subdir; + while(next_brother->next) next_brother = next_brother->next; + next_brother->next = this_dir; + }; + }; + +/* Now we scan the directory itself, and look at what is inside of it. */ + + dflag = 0; + while(1==1){ + + /* The first time through, skip this, since we already asked for + the first entry when we opened the directory. */ + if(dflag) d_entry = readdir_add_files(&path, old_path, current_dir); + dflag++; + + if(!d_entry) break; + + /* OK, got a valid entry */ + + /* If we do not want all files, then pitch the backups. */ + if(!all_files){ + if(strchr(d_entry->d_name,'~')) continue; + if(strchr(d_entry->d_name,'#')) continue; + }; + + if(strlen(path)+strlen(d_entry->d_name) + 2 > sizeof(whole_path)){ + fprintf(stderr, "Overflow of stat buffer\n"); + exit(1); + }; + + /* Generate the complete ASCII path for this file */ + strcpy(whole_path, path); +#ifndef VMS + if(whole_path[strlen(whole_path)-1] != '/') + strcat(whole_path, "/"); +#endif + strcat(whole_path, d_entry->d_name); + + /* Should we exclude this file? */ + if (is_excluded(whole_path)) { + if (verbose) { + fprintf(stderr, "Excluded: %s\n",whole_path); + } + continue; + } +#if 0 + if (verbose) fprintf(stderr, "%s\n",whole_path); +#endif + status = stat(whole_path, &statbuf); + + lstat(whole_path, &lstatbuf); + + if(this_dir == root && strcmp(d_entry->d_name, ".") == 0) + root_statbuf = statbuf; /* Save this for later on */ + + /* We do this to make sure that the root entries are consistent */ + if(this_dir == root && strcmp(d_entry->d_name, "..") == 0) { + statbuf = root_statbuf; + lstatbuf = root_statbuf; + }; + + if(S_ISLNK(lstatbuf.st_mode)){ + + /* Here we decide how to handle the symbolic links. Here + we handle the general case - if we are not following + links or there is an error, then we must change + something. If RR is in use, it is easy, we let RR + describe the file. If not, then we punt the file. */ + + if((status || !follow_links)){ + if(use_RockRidge){ + status = 0; + statbuf.st_size = 0; + STAT_INODE(statbuf) = UNCACHED_INODE; + statbuf.st_dev = (dev_t) UNCACHED_DEVICE; + statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG; + } else { + if(follow_links) fprintf(stderr, + "Unable to stat file %s - ignoring and continuing.\n", + whole_path); + else fprintf(stderr, + "Symlink %s ignored - continuing.\n", + whole_path); + continue; /* Non Rock Ridge discs - ignore all symlinks */ + }; + } + + /* Here we handle a different kind of case. Here we have + a symlink, but we want to follow symlinks. If we run + across a directory loop, then we need to pretend that + we are not following symlinks for this file. If this + is the first time we have seen this, then make this + seem as if there was no symlink there in the first + place */ + + if( follow_links + && S_ISDIR(statbuf.st_mode) ) + { + if( strcmp(d_entry->d_name, ".") + && strcmp(d_entry->d_name, "..") ) + { + if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) + { + if(!use_RockRidge) + { + fprintf(stderr, "Already cached directory seen (%s)\n", + whole_path); + continue; + } + statbuf.st_size = 0; + STAT_INODE(statbuf) = UNCACHED_INODE; + statbuf.st_dev = (dev_t) UNCACHED_DEVICE; + statbuf.st_mode = (statbuf.st_mode & ~S_IFMT) | S_IFREG; + } else { + lstatbuf = statbuf; + add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); + } + } + } + } + + /* + * Add directories to the cache so that we don't waste space even + * if we are supposed to be following symlinks. + */ + if( follow_links + && strcmp(d_entry->d_name, ".") + && strcmp(d_entry->d_name, "..") + && S_ISDIR(statbuf.st_mode) ) + { + add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); + } +#ifdef VMS + if(!S_ISDIR(lstatbuf.st_mode) && (statbuf.st_fab_rfm != FAB$C_FIX && + statbuf.st_fab_rfm != FAB$C_STMLF)) { + fprintf(stderr,"Warning - file %s has an unsupported VMS record" + " format (%d)\n", + whole_path, statbuf.st_fab_rfm); + } +#endif + + if(S_ISREG(lstatbuf.st_mode) && (status = access(whole_path, R_OK))){ + fprintf(stderr, "File %s is not readable (errno = %d) - ignoring\n", + whole_path, errno); + continue; + } + + /* Add this so that we can detect directory loops with hard links. + If we are set up to follow symlinks, then we skip this checking. */ + if( !follow_links + && S_ISDIR(lstatbuf.st_mode) + && strcmp(d_entry->d_name, ".") + && strcmp(d_entry->d_name, "..") ) + { + if(find_directory_hash(statbuf.st_dev, STAT_INODE(statbuf))) { + fprintf(stderr,"Directory loop - fatal goof (%s %lx %lu).\n", + whole_path, (unsigned long) statbuf.st_dev, + (unsigned long) STAT_INODE(statbuf)); + exit(1); + }; + add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf)); + }; + + if (!S_ISCHR(lstatbuf.st_mode) && !S_ISBLK(lstatbuf.st_mode) && + !S_ISFIFO(lstatbuf.st_mode) && !S_ISSOCK(lstatbuf.st_mode) + && !S_ISLNK(lstatbuf.st_mode) && !S_ISREG(lstatbuf.st_mode) && + !S_ISDIR(lstatbuf.st_mode)) { + fprintf(stderr,"Unknown file type %s - ignoring and continuing.\n", + whole_path); + continue; + }; + + /* Who knows what trash this is - ignore and continue */ + + if(status) { + fprintf(stderr, + "Unable to stat file %s - ignoring and continuing.\n", + whole_path); + continue; + }; + + s_entry = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + s_entry->next = this_dir->contents; + this_dir->contents = s_entry; + deep_flag = 0; + s_entry->table = NULL; + + s_entry->name = strdup(d_entry->d_name); + s_entry->whole_name = strdup (whole_path); + + s_entry->filedir = this_dir; + s_entry->isorec.flags[0] = 0; + s_entry->isorec.ext_attr_length[0] = 0; + iso9660_date(s_entry->isorec.date, statbuf.st_ctime); + s_entry->isorec.file_unit_size[0] = 0; + s_entry->isorec.interleave[0] = 0; + if(parent && parent == reloc_dir && strcmp(d_entry->d_name, "..") == 0){ + s_entry->inode = UNCACHED_INODE; + s_entry->dev = (dev_t) UNCACHED_DEVICE; + deep_flag = NEED_PL; + } else { + s_entry->inode = STAT_INODE(statbuf); + s_entry->dev = statbuf.st_dev; + }; + set_723(s_entry->isorec.volume_sequence_number, 1); + iso9660_file_length(d_entry->d_name, s_entry, S_ISDIR(statbuf.st_mode)); + s_entry->rr_attr_size = 0; + s_entry->total_rr_attr_size = 0; + s_entry->rr_attributes = NULL; + + /* Directories are assigned sizes later on */ + if (!S_ISDIR(statbuf.st_mode)) { + set_733(s_entry->isorec.size, statbuf.st_size); + + if (S_ISCHR(lstatbuf.st_mode) || S_ISBLK(lstatbuf.st_mode) || + S_ISFIFO(lstatbuf.st_mode) || S_ISSOCK(lstatbuf.st_mode) + || S_ISLNK(lstatbuf.st_mode)) + s_entry->size = 0; + else + s_entry->size = statbuf.st_size; + } else + s_entry->isorec.flags[0] = 2; + + if (strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..") && + S_ISDIR(statbuf.st_mode) && this_dir->depth > RR_relocation_depth){ + if(!reloc_dir) generate_reloc_directory(); + + s_entry1 = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memcpy(s_entry1, this_dir->contents, + sizeof(struct directory_entry)); + s_entry1->table = NULL; + s_entry1->name = strdup(this_dir->contents->name); + s_entry1->next = reloc_dir->contents; + reloc_dir->contents = s_entry1; + s_entry1->priority = 32768; + s_entry1->parent_rec = this_dir->contents; + + deep_flag = NEED_RE; + + if(use_RockRidge) { + generate_rock_ridge_attributes(whole_path, + d_entry->d_name, s_entry1, + &statbuf, &lstatbuf, deep_flag); + }; + + deep_flag = 0; + + /* We need to set this temporarily so that the parent to this is correctly + determined. */ + s_entry1->filedir = reloc_dir; + scan_directory_tree(whole_path, s_entry1); + s_entry1->filedir = this_dir; + + statbuf.st_size = 0; + statbuf.st_mode &= 0777; + set_733(s_entry->isorec.size, 0); + s_entry->size = 0; + s_entry->isorec.flags[0] = 0; + s_entry->inode = UNCACHED_INODE; + deep_flag = NEED_CL; + }; + + if(generate_tables && strcmp(s_entry->name, ".") && strcmp(s_entry->name, "..")) { + char buffer[2048]; + switch(lstatbuf.st_mode & S_IFMT){ + case S_IFDIR: + sprintf(buffer,"D\t%s\n", + s_entry->name); + break; +#ifndef NON_UNIXFS + case S_IFBLK: + sprintf(buffer,"B\t%s\t%lu %lu\n", + s_entry->name, + (unsigned long) major(statbuf.st_rdev), + (unsigned long) minor(statbuf.st_rdev)); + break; + case S_IFIFO: + sprintf(buffer,"P\t%s\n", + s_entry->name); + break; + case S_IFCHR: + sprintf(buffer,"C\t%s\t%lu %lu\n", + s_entry->name, + (unsigned long) major(statbuf.st_rdev), + (unsigned long) minor(statbuf.st_rdev)); + break; + case S_IFLNK: + readlink(whole_path, symlink_buff, sizeof(symlink_buff)); + sprintf(buffer,"L\t%s\t%s\n", + s_entry->name, symlink_buff); + break; + case S_IFSOCK: + sprintf(buffer,"S\t%s\n", + s_entry->name); + break; +#endif /* NON_UNIXFS */ + case S_IFREG: + default: + sprintf(buffer,"F\t%s\n", + s_entry->name); + break; + }; + s_entry->table = strdup(buffer); + }; + + if(S_ISDIR(statbuf.st_mode)){ + int dflag; + if (strcmp(d_entry->d_name,".") && strcmp(d_entry->d_name,"..")) { + dflag = scan_directory_tree(whole_path, s_entry); + /* If unable to scan directory, mark this as a non-directory */ + if(!dflag) + lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG; + } + }; + + if(use_RockRidge && this_dir == root && strcmp(s_entry->name, ".") == 0) + deep_flag |= NEED_CE | NEED_SP; /* For extension record */ + + /* Now figure out how much room this file will take in the directory */ + + if(use_RockRidge) { + generate_rock_ridge_attributes(whole_path, + d_entry->d_name, s_entry, + &statbuf, &lstatbuf, deep_flag); + + } + } + closedir(current_dir); + sort_n_finish(this_dir); + return 1; +} + + +void FDECL2(generate_iso9660_directories, struct directory *, node, FILE*, outfile){ + struct directory * dpnt; + + dpnt = node; + + while (dpnt){ + generate_one_directory(dpnt, outfile); + if(dpnt->subdir) generate_iso9660_directories(dpnt->subdir, outfile); + dpnt = dpnt->next; + }; +} + +void FDECL1(dump_tree, struct directory *, node){ + struct directory * dpnt; + + dpnt = node; + + while (dpnt){ + fprintf(stderr,"%4d %5d %s\n",dpnt->extent, dpnt->size, dpnt->de_name); + if(dpnt->subdir) dump_tree(dpnt->subdir); + dpnt = dpnt->next; + }; +} + diff --git a/gnu/usr.bin/mkisofs/write.c b/gnu/usr.bin/mkisofs/write.c new file mode 100644 index 000000000000..efe86cdb3de7 --- /dev/null +++ b/gnu/usr.bin/mkisofs/write.c @@ -0,0 +1,784 @@ +/* + * Program write.c - dump memory structures to file for iso9660 filesystem. + + Written by Eric Youngdale (1993). + + Copyright 1993 Yggdrasil Computing, Incorporated + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <string.h> +#include <stdlib.h> +#include "mkisofs.h" +#include "iso9660.h" +#include <time.h> +#include <errno.h> + +#ifdef __svr4__ +extern char * strdup(const char *); +#endif + +#ifdef VMS +extern char * strdup(const char *); +#endif + + +/* Max number of sectors we will write at one time */ +#define NSECT 16 + +/* Counters for statistics */ + +static int table_size = 0; +static int total_dir_size = 0; +static int rockridge_size = 0; +static struct directory ** pathlist; +static next_path_index = 1; + +/* Used to fill in some of the information in the volume descriptor. */ +static struct tm *local; + +/* Routines to actually write the disc. We write sequentially so that + we could write a tape, or write the disc directly */ + + +#define FILL_SPACE(X) memset(vol_desc.X, ' ', sizeof(vol_desc.X)) + +void FDECL2(set_721, char *, pnt, unsigned int, i){ + pnt[0] = i & 0xff; + pnt[1] = (i >> 8) & 0xff; +} + +void FDECL2(set_722, char *, pnt, unsigned int, i){ + pnt[0] = (i >> 8) & 0xff; + pnt[1] = i & 0xff; +} + +void FDECL2(set_723, char *, pnt, unsigned int, i){ + pnt[3] = pnt[0] = i & 0xff; + pnt[2] = pnt[1] = (i >> 8) & 0xff; +} + +void FDECL2(set_731, char *, pnt, unsigned int, i){ + pnt[0] = i & 0xff; + pnt[1] = (i >> 8) & 0xff; + pnt[2] = (i >> 16) & 0xff; + pnt[3] = (i >> 24) & 0xff; +} + +void FDECL2(set_732, char *, pnt, unsigned int, i){ + pnt[3] = i & 0xff; + pnt[2] = (i >> 8) & 0xff; + pnt[1] = (i >> 16) & 0xff; + pnt[0] = (i >> 24) & 0xff; +} + +int FDECL1(get_733, char *, p){ + return ((p[0] & 0xff) + | ((p[1] & 0xff) << 8) + | ((p[2] & 0xff) << 16) + | ((p[3] & 0xff) << 24)); +} + +void FDECL2(set_733, char *, pnt, unsigned int, i){ + pnt[7] = pnt[0] = i & 0xff; + pnt[6] = pnt[1] = (i >> 8) & 0xff; + pnt[5] = pnt[2] = (i >> 16) & 0xff; + pnt[4] = pnt[3] = (i >> 24) & 0xff; +} + +static FDECL4(xfwrite, void *, buffer, int, count, int, size, FILE *, file) +{ + while(count) { + int got=fwrite(buffer,size,count,file); + if(got<=0) fprintf(stderr,"cannot fwrite %d*%d\n",size,count),exit(1); + count-=got,*(char**)&buffer+=size*got; + } +} + +struct deferred_write{ + struct deferred_write * next; + char * table; + unsigned int extent; + unsigned int size; + char * name; +}; + +static struct deferred_write * dw_head = NULL, * dw_tail = NULL; + +static struct directory_entry * sort_dir; + +unsigned int last_extent_written =0; +static struct iso_primary_descriptor vol_desc; +static path_table_index; + +/* We recursively walk through all of the directories and assign extent + numbers to them. We have already assigned extent numbers to everything that + goes in front of them */ + +void FDECL1(assign_directory_addresses, struct directory *, node){ + struct directory * dpnt; + int dir_size; + + dpnt = node; + + while (dpnt){ + dpnt->extent = last_extent; + dpnt->path_index = next_path_index++; + dir_size = (dpnt->size + (SECTOR_SIZE - 1)) >> 11; + + last_extent += dir_size; + + /* Leave room for the CE entries for this directory. Keep them + close to the reference directory so that access will be quick. */ + if(dpnt->ce_bytes) + last_extent += ROUND_UP(dpnt->ce_bytes) >> 11; + + if(dpnt->subdir) assign_directory_addresses(dpnt->subdir); + dpnt = dpnt->next; + }; +} + +static void FDECL3(write_one_file, char *, filename, unsigned int, size, FILE *, outfile){ + FILE * infile; + char buffer[SECTOR_SIZE * NSECT]; + int use; + int remain; + if ((infile = fopen(filename, "rb")) == NULL) { +#ifdef sun + fprintf(stderr, "cannot open %s: (%d)\n", filename, errno); +#else + fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno)); +#endif + exit(1); + } + remain = size; + + while(remain > 0){ + use = (remain > SECTOR_SIZE * NSECT - 1 ? NSECT*SECTOR_SIZE : remain); + use = ROUND_UP(use); /* Round up to nearest sector boundary */ + memset(buffer, 0, use); + if (fread(buffer, 1, use, infile) == 0) { + fprintf(stderr,"cannot read from %s\n",filename); + exit(1); + } + xfwrite(buffer, 1, use, outfile); + last_extent_written += use/SECTOR_SIZE; + if((last_extent_written % 1000) < use/SECTOR_SIZE) fprintf(stderr,"%d..", last_extent_written); + remain -= use; + }; + fclose(infile); +} + +static void FDECL1(write_files, FILE *, outfile){ + struct deferred_write * dwpnt, *dwnext; + dwpnt = dw_head; + while(dwpnt){ + if(dwpnt->table) { + xfwrite(dwpnt->table, 1, ROUND_UP(dwpnt->size), outfile); + last_extent_written += ROUND_UP(dwpnt->size) / SECTOR_SIZE; + table_size += dwpnt->size; +/* fprintf(stderr,"Size %d ", dwpnt->size); */ + free(dwpnt->table); + } else { + +#ifdef VMS + vms_write_one_file(dwpnt->name, dwpnt->size, outfile); +#else + write_one_file(dwpnt->name, dwpnt->size, outfile); +#endif + free(dwpnt->name); + }; + + dwnext = dwpnt; + dwpnt = dwpnt->next; + free(dwnext); + }; +} + +#if 0 +static void dump_filelist(){ + struct deferred_write * dwpnt; + dwpnt = dw_head; + while(dwpnt){ + fprintf(stderr, "File %s\n",dwpnt->name); + dwpnt = dwpnt->next; + }; + fprintf(stderr,"\n"); +}; +#endif + +int FDECL2(compare_dirs, const struct directory_entry **, r, const struct directory_entry **, l) { + char * rpnt, *lpnt; + + rpnt = (*r)->isorec.name; + lpnt = (*l)->isorec.name; + + while(*rpnt && *lpnt) { + if(*rpnt == ';' && *lpnt != ';') return -1; + if(*rpnt != ';' && *lpnt == ';') return 1; + if(*rpnt == ';' && *lpnt == ';') return 0; + if(*rpnt < *lpnt) return -1; + if(*rpnt > *lpnt) return 1; + rpnt++; lpnt++; + } + if(*rpnt) return 1; + if(*lpnt) return -1; + return 0; +} + +void FDECL1(sort_directory, struct directory_entry **, sort_dir){ + int dcount = 0; + int i, len; + struct directory_entry * s_entry; + struct directory_entry ** sortlist; + + s_entry = *sort_dir; + while(s_entry){ + dcount++; + s_entry = s_entry->next; + }; + /* OK, now we know how many there are. Build a vector for sorting. */ + + sortlist = (struct directory_entry **) + e_malloc(sizeof(struct directory_entry *) * dcount); + + dcount = 0; + s_entry = *sort_dir; + while(s_entry){ + sortlist[dcount] = s_entry; + len = s_entry->isorec.name_len[0]; + s_entry->isorec.name[len] = 0; + dcount++; + s_entry = s_entry->next; + }; + + qsort(sortlist, dcount, sizeof(struct directory_entry *), compare_dirs); + + /* Now reassemble the linked list in the proper sorted order */ + for(i=0; i<dcount-1; i++) + sortlist[i]->next = sortlist[i+1]; + + sortlist[dcount-1]->next = NULL; + *sort_dir = sortlist[0]; + + free(sortlist); + +} + +void generate_root_record(){ + time_t ctime; + + time (&ctime); + local = localtime(&ctime); + + root_record.length[0] = 1 + sizeof(struct iso_directory_record); + root_record.ext_attr_length[0] = 0; + set_733(root_record.extent, root->extent); + set_733(root_record.size, ROUND_UP(root->size)); + iso9660_date(root_record.date, ctime); + root_record.flags[0] = 2; + root_record.file_unit_size[0] = 0; + root_record.interleave[0] = 0; + set_723(root_record.volume_sequence_number, 1); + root_record.name_len[0] = 1; +} + +static void FDECL1(assign_file_addresses, struct directory *, dpnt){ + struct directory * finddir; + struct directory_entry * s_entry; + struct file_hash *s_hash; + struct deferred_write * dwpnt; + char whole_path[1024]; + + while (dpnt){ + s_entry = dpnt->contents; + for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next){ + + /* This saves some space if there are symlinks present */ + s_hash = find_hash(s_entry->dev, s_entry->inode); + if(s_hash){ + if(verbose) + fprintf(stderr, "Cache hit for %s%s%s\n",s_entry->filedir->de_name, + SPATH_SEPARATOR, s_entry->name); + set_733(s_entry->isorec.extent, s_hash->starting_block); + set_733(s_entry->isorec.size, s_hash->size); + continue; + }; + if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..") && + s_entry->isorec.flags[0] == 2){ + finddir = dpnt->subdir; + while(1==1){ + if(finddir->self == s_entry) break; + finddir = finddir->next; + if(!finddir) {fprintf(stderr,"Fatal goof\n"); exit(1);}; + }; + set_733(s_entry->isorec.extent, finddir->extent); + s_entry->starting_block = finddir->extent; + s_entry->size = ROUND_UP(finddir->size); + total_dir_size += s_entry->size; + add_hash(s_entry); + set_733(s_entry->isorec.size, ROUND_UP(finddir->size)); + } else { + if(strcmp(s_entry->name,".") ==0 || strcmp(s_entry->name,"..") == 0) { + if(strcmp(s_entry->name,".") == 0) { + set_733(s_entry->isorec.extent, dpnt->extent); + + /* Set these so that the hash table has the correct information */ + s_entry->starting_block = dpnt->extent; + s_entry->size = ROUND_UP(dpnt->size); + + add_hash(s_entry); + s_entry->starting_block = dpnt->extent; + set_733(s_entry->isorec.size, ROUND_UP(dpnt->size)); + } else { + if(dpnt == root) total_dir_size += root->size; + set_733(s_entry->isorec.extent, dpnt->parent->extent); + + /* Set these so that the hash table has the correct information */ + s_entry->starting_block = dpnt->parent->extent; + s_entry->size = ROUND_UP(dpnt->parent->size); + + add_hash(s_entry); + s_entry->starting_block = dpnt->parent->extent; + set_733(s_entry->isorec.size, ROUND_UP(dpnt->parent->size)); + }; + } else { + /* Now we schedule the file to be written. This is all quite + straightforward, just make a list and assign extents as we go. + Once we get through writing all of the directories, we should + be ready write out these files */ + + if(s_entry->size) { + dwpnt = (struct deferred_write *) + e_malloc(sizeof(struct deferred_write)); + if(dw_tail){ + dw_tail->next = dwpnt; + dw_tail = dwpnt; + } else { + dw_head = dwpnt; + dw_tail = dwpnt; + }; + if(s_entry->inode == TABLE_INODE) { + dwpnt->table = s_entry->table; + dwpnt->name = NULL; + } else { + dwpnt->table = NULL; + strcpy(whole_path, s_entry->whole_name); + dwpnt->name = strdup(whole_path); + }; + dwpnt->next = NULL; + dwpnt->size = s_entry->size; + dwpnt->extent = last_extent; + set_733(s_entry->isorec.extent, last_extent); + s_entry->starting_block = last_extent; + add_hash(s_entry); + last_extent += ROUND_UP(s_entry->size) >> 11; + if(verbose) + fprintf(stderr,"%d %d %s\n", s_entry->starting_block, + last_extent-1, whole_path); +#ifdef DBG_ISO + if((ROUND_UP(s_entry->size) >> 11) > 500){ + fprintf(stderr,"Warning: large file %s\n", whole_path); + fprintf(stderr,"Starting block is %d\n", s_entry->starting_block); + fprintf(stderr,"Reported file size is %d extents\n", s_entry->size); + + }; +#endif + if(last_extent > (700000000 >> 11)) { /* More than 700Mb? Punt */ + fprintf(stderr,"Extent overflow processing file %s\n", whole_path); + fprintf(stderr,"Starting block is %d\n", s_entry->starting_block); + fprintf(stderr,"Reported file size is %d extents\n", s_entry->size); + exit(1); + }; + } else { + /* + * This is for zero-length files. If we leave the extent 0, + * then we get screwed, because many readers simply drop files + * that have an extent of zero. Thus we leave the size 0, + * and just assign the extent number. + */ + set_733(s_entry->isorec.extent, last_extent); + } + }; + }; + }; + if(dpnt->subdir) assign_file_addresses(dpnt->subdir); + dpnt = dpnt->next; + }; +} + +void FDECL2(generate_one_directory, struct directory *, dpnt, FILE *, outfile){ + unsigned int total_size, ce_size; + char * directory_buffer; + char * ce_buffer; + unsigned int ce_address; + struct directory_entry * s_entry, *s_entry_d; + int new_reclen; + unsigned int dir_index, ce_index; + + total_size = (dpnt->size + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1); + directory_buffer = (char *) e_malloc(total_size); + memset(directory_buffer, 0, total_size); + dir_index = 0; + + ce_size = (dpnt->ce_bytes + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1); + ce_buffer = NULL; + + if(ce_size) { + ce_buffer = (char *) e_malloc(ce_size); + memset(ce_buffer, 0, ce_size); + + ce_index = 0; + + /* Absolute byte address of CE entries for this directory */ + ce_address = last_extent_written + (total_size >> 11); + ce_address = ce_address << 11; + } + + s_entry = dpnt->contents; + while(s_entry) { + + /* We do not allow directory entries to cross sector boundaries. Simply + pad, and then start the next entry at the next sector */ + new_reclen = s_entry->isorec.length[0]; + if ((dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE) + dir_index = (dir_index + (SECTOR_SIZE - 1)) & + ~(SECTOR_SIZE - 1); + + memcpy(directory_buffer + dir_index, &s_entry->isorec, + sizeof(struct iso_directory_record) - + sizeof(s_entry->isorec.name) + s_entry->isorec.name_len[0]); + dir_index += sizeof(struct iso_directory_record) - + sizeof (s_entry->isorec.name)+ s_entry->isorec.name_len[0]; + + /* Add the Rock Ridge attributes, if present */ + if(s_entry->rr_attr_size){ + if(dir_index & 1) + directory_buffer[dir_index++] = 0; + + /* If the RR attributes were too long, then write the CE records, + as required. */ + if(s_entry->rr_attr_size != s_entry->total_rr_attr_size) { + unsigned char * pnt; + int len, nbytes; + + /* Go through the entire record and fix up the CE entries + so that the extent and offset are correct */ + + pnt = s_entry->rr_attributes; + len = s_entry->total_rr_attr_size; + while(len > 3){ + if(pnt[0] == 'C' && pnt[1] == 'E') { + nbytes = get_733(pnt+20); + + if((ce_index & (SECTOR_SIZE - 1)) + nbytes >= + SECTOR_SIZE) ce_index = ROUND_UP(ce_index); + + set_733(pnt+4, (ce_address + ce_index) >> 11); + set_733(pnt+12, (ce_address + ce_index) & (SECTOR_SIZE - 1)); + + + /* Now store the block in the ce buffer */ + memcpy(ce_buffer + ce_index, + pnt + pnt[2], nbytes); + ce_index += nbytes; + if(ce_index & 1) ce_index++; + }; + len -= pnt[2]; + pnt += pnt[2]; + }; + + } + + rockridge_size += s_entry->total_rr_attr_size; + memcpy(directory_buffer + dir_index, s_entry->rr_attributes, + s_entry->rr_attr_size); + dir_index += s_entry->rr_attr_size; + }; + if(dir_index & 1) + directory_buffer[dir_index++] = 0; + + s_entry_d = s_entry; + s_entry = s_entry->next; + + if (s_entry_d->rr_attributes) free(s_entry_d->rr_attributes); + free (s_entry_d->name); + free (s_entry_d); + }; + sort_dir = NULL; + + if(dpnt->size != dir_index) + fprintf(stderr,"Unexpected directory length %d %d %s\n",dpnt->size, + dir_index, dpnt->de_name); + xfwrite(directory_buffer, 1, total_size, outfile); + last_extent_written += total_size >> 11; + free(directory_buffer); + + if(ce_size){ + if(ce_index != dpnt->ce_bytes) + fprintf(stderr,"Continuation entry record length mismatch (%d %d).\n", + ce_index, dpnt->ce_bytes); + xfwrite(ce_buffer, 1, ce_size, outfile); + last_extent_written += ce_size >> 11; + free(ce_buffer); + } + +} + +static void FDECL1(build_pathlist, struct directory *, node){ + struct directory * dpnt; + + dpnt = node; + + while (dpnt){ + pathlist[dpnt->path_index] = dpnt; + if(dpnt->subdir) build_pathlist(dpnt->subdir); + dpnt = dpnt->next; + }; +} + +int FDECL2(compare_paths, const struct directory **, r, const struct directory **, l) { + if((*r)->parent->path_index < (*l)->parent->path_index) return -1; + if((*r)->parent->path_index > (*l)->parent->path_index) return 1; + return strcmp((*r)->self->isorec.name, (*l)->self->isorec.name); + +} + +void generate_path_tables(){ + struct directory * dpnt; + char * npnt, *npnt1; + int namelen; + struct directory_entry * de; + int fix; + int tablesize; + int i,j; + /* First allocate memory for the tables and initialize the memory */ + + tablesize = path_blocks << 11; + path_table_m = (char *) e_malloc(tablesize); + path_table_l = (char *) e_malloc(tablesize); + memset(path_table_l, 0, tablesize); + memset(path_table_m, 0, tablesize); + + /* Now start filling in the path tables. Start with root directory */ + path_table_index = 0; + pathlist = (struct directory **) e_malloc(sizeof(struct directory *) * next_path_index); + memset(pathlist, 0, sizeof(struct directory *) * next_path_index); + build_pathlist(root); + + do{ + fix = 0; + qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *), compare_paths); + + for(j=1; j<next_path_index; j++) + if(pathlist[j]->path_index != j){ + pathlist[j]->path_index = j; + fix++; + }; + } while(fix); + + for(j=1; j<next_path_index; j++){ + dpnt = pathlist[j]; + if(!dpnt){ + fprintf(stderr,"Entry %d not in path tables\n", j); + exit(1); + }; + npnt = dpnt->de_name; + if(*npnt == 0 || dpnt == root) npnt = "."; /* So the root comes out OK */ + npnt1 = strrchr(npnt, PATH_SEPARATOR); + if(npnt1) npnt = npnt1 + 1; + + de = dpnt->self; + if(!de) {fprintf(stderr,"Fatal goof\n"); exit(1);}; + + + namelen = de->isorec.name_len[0]; + + path_table_l[path_table_index] = namelen; + path_table_m[path_table_index] = namelen; + path_table_index += 2; + set_731(path_table_l + path_table_index, dpnt->extent); + set_732(path_table_m + path_table_index, dpnt->extent); + path_table_index += 4; + set_721(path_table_l + path_table_index, dpnt->parent->path_index); + set_722(path_table_m + path_table_index, dpnt->parent->path_index); + path_table_index += 2; + for(i =0; i<namelen; i++){ + path_table_l[path_table_index] = de->isorec.name[i]; + path_table_m[path_table_index] = de->isorec.name[i]; + path_table_index++; + }; + if(path_table_index & 1) path_table_index++; /* For odd lengths we pad */ + }; + free(pathlist); + if(path_table_index != path_table_size) + fprintf(stderr,"Path table lengths do not match %d %d\n",path_table_index, + path_table_size); +} + +int FDECL1(iso_write, FILE *, outfile){ + char buffer[2048]; + char iso_time[17]; + int should_write; + int i; + + assign_file_addresses(root); + + memset(buffer, 0, sizeof(buffer)); + + /* This will break in the year 2000, I supose, but there is no good way + to get the top two digits of the year. */ + sprintf(iso_time, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d00", 1900 + local->tm_year, + local->tm_mon+1, local->tm_mday, + local->tm_hour, local->tm_min, local->tm_sec); + + /* First, we output 16 sectors of all zero */ + + for(i=0; i<16; i++) + xfwrite(buffer, 1, sizeof(buffer), outfile); + + last_extent_written += 16; + + /* Next we write out the primary descriptor for the disc */ + memset(&vol_desc, 0, sizeof(vol_desc)); + vol_desc.type[0] = ISO_VD_PRIMARY; + memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID)); + vol_desc.version[0] = 1; + + memset(vol_desc.system_id, ' ', sizeof(vol_desc.system_id)); + memcpy(vol_desc.system_id, system_id, strlen(system_id)); + + memset(vol_desc.volume_id, ' ', sizeof(vol_desc.volume_id)); + memcpy(vol_desc.volume_id, volume_id, strlen(volume_id)); + + should_write = last_extent; + set_733(vol_desc.volume_space_size, last_extent); + set_723(vol_desc.volume_set_size, 1); + set_723(vol_desc.volume_sequence_number, 1); + set_723(vol_desc.logical_block_size, 2048); + + /* The path tables are used by DOS based machines to cache directory + locations */ + + set_733(vol_desc.path_table_size, path_table_size); + set_731(vol_desc.type_l_path_table, path_table[0]); + set_731(vol_desc.opt_type_l_path_table, path_table[1]); + set_732(vol_desc.type_m_path_table, path_table[2]); + set_732(vol_desc.opt_type_m_path_table, path_table[3]); + + /* Now we copy the actual root directory record */ + + memcpy(vol_desc.root_directory_record, &root_record, + sizeof(struct iso_directory_record) + 1); + + /* The rest is just fluff. It looks nice to fill in many of these fields, + though */ + + FILL_SPACE(volume_set_id); + if(volset_id) memcpy(vol_desc.volume_set_id, volset_id, strlen(volset_id)); + + FILL_SPACE(publisher_id); + if(publisher) memcpy(vol_desc.publisher_id, publisher, strlen(publisher)); + + FILL_SPACE(preparer_id); + if(preparer) memcpy(vol_desc.preparer_id, preparer, strlen(preparer)); + + FILL_SPACE(application_id); + if(appid) memcpy(vol_desc.application_id, appid, strlen(appid)); + + FILL_SPACE(copyright_file_id); + if(appid) memcpy(vol_desc.copyright_file_id, appid, strlen(appid)); + + FILL_SPACE(abstract_file_id); + if(appid) memcpy(vol_desc.abstract_file_id, appid, strlen(appid)); + + FILL_SPACE(bibliographic_file_id); + if(appid) memcpy(vol_desc.bibliographic_file_id, appid, strlen(appid)); + + FILL_SPACE(creation_date); + FILL_SPACE(modification_date); + FILL_SPACE(expiration_date); + FILL_SPACE(effective_date); + vol_desc.file_structure_version[0] = 1; + FILL_SPACE(application_data); + + memcpy(vol_desc.creation_date, iso_time, 16); + memcpy(vol_desc.modification_date, iso_time, 16); + memcpy(vol_desc.expiration_date, "0000000000000000", 16); + memcpy(vol_desc.effective_date, iso_time, 16); + + /* For some reason, Young Minds writes this twice. Aw, what the heck */ + xfwrite(&vol_desc, 1, 2048, outfile); + xfwrite(&vol_desc, 1, 2048, outfile); + last_extent_written += 2; + + /* Now write the end volume descriptor. Much simpler than the other one */ + memset(&vol_desc, 0, sizeof(vol_desc)); + vol_desc.type[0] = ISO_VD_END; + memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID)); + vol_desc.version[0] = 1; + xfwrite(&vol_desc, 1, 2048, outfile); + xfwrite(&vol_desc, 1, 2048, outfile); + last_extent_written += 2; + + /* Next we write the path tables */ + xfwrite(path_table_l, 1, path_blocks << 11, outfile); + xfwrite(path_table_l, 1, path_blocks << 11, outfile); + xfwrite(path_table_m, 1, path_blocks << 11, outfile); + xfwrite(path_table_m, 1, path_blocks << 11, outfile); + last_extent_written += 4*path_blocks; + free(path_table_l); + free(path_table_m); + path_table_l = NULL; + path_table_m = NULL; + + /* OK, all done with that crap. Now write out the directories. + This is where the fur starts to fly, because we need to keep track of + each file as we find it and keep track of where we put it. */ + +#ifdef DBG_ISO + fprintf(stderr,"Total directory extents being written = %d\n", last_extent); +#endif +#if 0 + generate_one_directory(root, outfile); +#endif + generate_iso9660_directories(root, outfile); + + if(extension_record) { + xfwrite(extension_record, 1, SECTOR_SIZE, outfile); + last_extent_written++; + } + + /* Now write all of the files that we need. */ + fprintf(stderr,"Total extents scheduled to be written = %d\n", last_extent); + write_files(outfile); + + fprintf(stderr,"Total extents actually written = %d\n", last_extent_written); + /* Hard links throw us off here */ + if(should_write != last_extent){ + fprintf(stderr,"Number of extents written not what was predicted. Please fix.\n"); + fprintf(stderr,"Predicted = %d, written = %d\n", should_write, last_extent); + }; + + fprintf(stderr,"Total translation table size: %d\n", table_size); + fprintf(stderr,"Total rockridge attributes bytes: %d\n", rockridge_size); + fprintf(stderr,"Total directory bytes: %d\n", total_dir_size); + fprintf(stderr,"Path table size(bytes): %d\n", path_table_size); +#ifdef DEBUG + fprintf(stderr, "next extent, last_extent, last_extent_written %d %d %d\n", + next_extent, last_extent, last_extent_written); +#endif + return 0; +} |
