summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoerg Wunsch <joerg@FreeBSD.org>1995-10-22 10:11:03 +0000
committerJoerg Wunsch <joerg@FreeBSD.org>1995-10-22 10:11:03 +0000
commit3f2e9a763fabff16dd209e3f7c59c5922574682f (patch)
treef5dea9912f17202d9e3dddd7cde2bdb65f77f7e5
Notes
-rw-r--r--gnu/usr.bin/mkisofs/ChangeLog695
-rw-r--r--gnu/usr.bin/mkisofs/Makefile.in51
-rw-r--r--gnu/usr.bin/mkisofs/README84
-rw-r--r--gnu/usr.bin/mkisofs/defaults.h25
-rw-r--r--gnu/usr.bin/mkisofs/diag/Makefile16
-rw-r--r--gnu/usr.bin/mkisofs/diag/isodump.c436
-rw-r--r--gnu/usr.bin/mkisofs/diag/isoinfo.c522
-rw-r--r--gnu/usr.bin/mkisofs/diag/isovfy.c490
-rw-r--r--gnu/usr.bin/mkisofs/exclude.c54
-rw-r--r--gnu/usr.bin/mkisofs/mkisofs.8274
-rw-r--r--gnu/usr.bin/mkisofs/mkisofs.c721
-rw-r--r--gnu/usr.bin/mkisofs/mkisofs.h263
-rw-r--r--gnu/usr.bin/mkisofs/rock.c530
-rw-r--r--gnu/usr.bin/mkisofs/tree.c1012
-rw-r--r--gnu/usr.bin/mkisofs/write.c784
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(&sector[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(&sector[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(&sector[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", &copyright},
+ {"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 (&current_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 (&current_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;
+}