Import version 1.04 of mkisofs.

This is a vendor-branch import by now, the merge with our regular
tree will happen later.

Obtained from: Eric Youngdale of Yggdrasil Computing Inc.
This commit is contained in:
Joerg Wunsch 1995-10-22 10:11:03 +00:00
commit 3f2e9a763f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/mkisofs/; revision=11646
15 changed files with 5957 additions and 0 deletions

View File

@ -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.

View File

@ -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

View File

@ -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).

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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");
}

View File

@ -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 */
}

View File

@ -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.

View File

@ -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;
}

View File

@ -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

530
gnu/usr.bin/mkisofs/rock.c Normal file
View File

@ -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;
}

1012
gnu/usr.bin/mkisofs/tree.c Normal file

File diff suppressed because it is too large Load Diff

784
gnu/usr.bin/mkisofs/write.c Normal file
View File

@ -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;
}